上传多个文件并查询 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)

    }
  };