上传多个文件并查询 Firestore DB - ReactJS
Upload multiple files and query Firestore DB - ReactJS
我之前已经阅读了很多关于这个问题的帖子,比如这个 ,我尝试了不同的选项,但无法得到我的结果。
我正在将 React Hook Form 用于一个非常巨大的表单,现在我必须添加更多输入(以上传文件),并且需要帮助一次完成所有事情。
我更新一个文件的代码:
const onChangeFile = async (e: any) => {
const file = e.target.files[0];
const storageRef = app.storage().ref();
const fileRef = storageRef.child(file.name);
await fileRef.put(file);
setFileUrl(await fileRef.getDownloadURL());
};
const onSubmit = async (data: any) => {
try {
await db
.collection('listings')
.doc()
.set({ ...data, created: new Date(), uid: currentUser.uid, file: fileUrl });
reset();
} catch (error) {
}
};
因此,如您所见,只上传一个文件非常简单,但上传多个文件时情况就不同了。问题是,我需要在我的 onSubmit 中使用更多函数,它本身就是一个异步函数,所以这限制了我在其中可以做的事情的数量。
有人有简单的解决方法吗?
如果 e.target.files
有多个文件,那么您可以将上传操作推送到一个数组,然后使用 Promise.all()
:
上传它们
const onChangeFile = async (e: any) => {
const storageRef = app.storage().ref();
const fileUploads = e.target.files.map(file => storageRef.child(file.name).put(file));
const fileURLReqs = (await Promise.all(fileUploads)).map(f => f.ref.getDownloadURL())
const fileUrls = await Promise.all(fileURLReqs)
// setFileUrl(await fileRef.getDownloadURL());
};
fileUrls
将是所有上传图像的 URL 数组,如果需要,onSubmit
可以将其上传到 Firestore。
我不确定您是否要为每张图片添加新文档,但如果是,请试试这个:
// in onSubmit
const listingsCol = db.collection("listings")
const files = [] // get that fileUrls array from your state
const updates = files.map(file => listingsCol.add({...data, file}))
await Promise.all(updates)
// this will add a new document for each new file uploaded
感谢@Dharmaraj,我得到了这个热门问题的简单工作版本,我认为他已经给出了一个非常清晰和直接的解决方案,功劳完全归于他。
尽管如此,我的实现可能有弱点,即使它有效(到目前为止),所以我想post它,你可以使用它或指出可能的危险信号。
const Form: React.FC = () => {
const [filesUrl, setFilesUrl] = useState<any[]>([]);
const { register, handleSubmit, reset } = useForm({ defaultValues });
const onChangeFile = async (e: any) => {
const storageRef = app.storage().ref();
const fileUploads = Array.from(e.target.files).map((file: any) => storageRef.child(file.name).put(file));
const fileURLReqs = (await Promise.all(fileUploads)).map((f: any) => f.ref.getDownloadURL());
const fileUrls = await Promise.all(fileURLReqs);
setFilesUrl(fileUrls);
};
const onSubmit = async (data: any) => {
try {
await db
.collection('collName')
.doc()
.set({ ...data, created: new Date(), uid: currentUser.uid, file: filesUrl });
reset();
} catch (error) {
console.log(error)
}
};
我之前已经阅读了很多关于这个问题的帖子,比如这个
我更新一个文件的代码:
const onChangeFile = async (e: any) => {
const file = e.target.files[0];
const storageRef = app.storage().ref();
const fileRef = storageRef.child(file.name);
await fileRef.put(file);
setFileUrl(await fileRef.getDownloadURL());
};
const onSubmit = async (data: any) => {
try {
await db
.collection('listings')
.doc()
.set({ ...data, created: new Date(), uid: currentUser.uid, file: fileUrl });
reset();
} catch (error) {
}
};
因此,如您所见,只上传一个文件非常简单,但上传多个文件时情况就不同了。问题是,我需要在我的 onSubmit 中使用更多函数,它本身就是一个异步函数,所以这限制了我在其中可以做的事情的数量。 有人有简单的解决方法吗?
如果 e.target.files
有多个文件,那么您可以将上传操作推送到一个数组,然后使用 Promise.all()
:
const onChangeFile = async (e: any) => {
const storageRef = app.storage().ref();
const fileUploads = e.target.files.map(file => storageRef.child(file.name).put(file));
const fileURLReqs = (await Promise.all(fileUploads)).map(f => f.ref.getDownloadURL())
const fileUrls = await Promise.all(fileURLReqs)
// setFileUrl(await fileRef.getDownloadURL());
};
fileUrls
将是所有上传图像的 URL 数组,如果需要,onSubmit
可以将其上传到 Firestore。
我不确定您是否要为每张图片添加新文档,但如果是,请试试这个:
// in onSubmit
const listingsCol = db.collection("listings")
const files = [] // get that fileUrls array from your state
const updates = files.map(file => listingsCol.add({...data, file}))
await Promise.all(updates)
// this will add a new document for each new file uploaded
感谢@Dharmaraj,我得到了这个热门问题的简单工作版本,我认为他已经给出了一个非常清晰和直接的解决方案,功劳完全归于他。
尽管如此,我的实现可能有弱点,即使它有效(到目前为止),所以我想post它,你可以使用它或指出可能的危险信号。
const Form: React.FC = () => {
const [filesUrl, setFilesUrl] = useState<any[]>([]);
const { register, handleSubmit, reset } = useForm({ defaultValues });
const onChangeFile = async (e: any) => {
const storageRef = app.storage().ref();
const fileUploads = Array.from(e.target.files).map((file: any) => storageRef.child(file.name).put(file));
const fileURLReqs = (await Promise.all(fileUploads)).map((f: any) => f.ref.getDownloadURL());
const fileUrls = await Promise.all(fileURLReqs);
setFilesUrl(fileUrls);
};
const onSubmit = async (data: any) => {
try {
await db
.collection('collName')
.doc()
.set({ ...data, created: new Date(), uid: currentUser.uid, file: filesUrl });
reset();
} catch (error) {
console.log(error)
}
};