我需要使用 React Dropzone 验证上传视频的持续时间。问题是我发现的每个方法都是异步的,而库的验证器函数应该是同步的。如何在同步函数中运行异步代码?
获取视频持续时间函数:
async function getVideoDuration(videoFile: File | Blob) {
return new Promise<number>((res, _) => {
const video = document.createElement("video")
video.preload = "metadata"
video.onloadeddata = function () {
res(video.duration)
}
video.src = URL.createObjectURL(videoFile)
})
}
我的 React Zone 验证器功能:
validator(f) {
let file: (File) | null
if (f instanceof DataTransferItem) {
file = f.getAsFile()
} else file = f
if (!file) return { message: "File Expected", code: "IvalidDragObject" }
console.log(file)
if (file.size > 5e8) return { message: "File too large (max 500 MB)", code: "FileTooLarge" }
if (!file) return { message: "File Expected", code: "IvalidDragObject" }
const duration = await getVideoDuration(file) // 'await' expressions are only allowed within async functions and at the top levels of modules.
if (duration > 15 * 60) {
return { message: "File Duration should be less than 15 minutes", code: "LargeFileDuration" }
}
return null
},
其他解决方法是使用 getFilesFromEvent
函数并将自定义 Prop 传递给那里的文件,但它提供的事件非常不同,而且实现起来很繁琐。
最佳答案
我已经 fork 了这个项目 here进行必要的更改以支持异步验证。请注意,目前不支持 noDragEventsBubbling
参数。只需传入异步(或同步)验证回调函数(如下所示),然后按最初的预期使用。
import { useDropzone } from 'react-dropzone'
function MyDropzone() {
const onDrop = useCallback(acceptedFiles => {
// Do something with the files
}, [])
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
validator: async (file) => {
// do validation here
}
})
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop the files here ...</p> :
<p>Drag 'n' drop some files here, or click to select files</p>
}
</div>
)
}
关于javascript - 上传文件的异步验证(React Dropzone + TS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75905513/