【问题标题】:upload multiple files to firebase storage issues将多个文件上传到 Firebase 存储问题
【发布时间】:2019-08-18 08:40:21
【问题描述】:

我正在开发一个以 firebase 为后端的烹饪 android 应用程序,我需要在 firebase stoarge 中上传多个食谱图像,然后将下载网址存储到 firebase 数据库中。

我设法将文件上传到 firebase,但在获取这些文件的 downloadUrl 时遇到了一些麻烦。 我已经创建了一组承诺来上传文件,并且我已经创建了另一个数组来存储我在完成上传任务时获得的每个文件的 url。

这是我的代码

 var promises = [];
 for (var i=0 ;i< prepaImages.length;i++) 
            {
                //alert(prepaImages[i].name);

              var storageRef = firebase.storage().ref("receipes"+"/"+category+"/"+title+"/"+uploadTime+prepaImages[i].name );
             var uploadTask = storageRef.put(prepaImages[i]);
              promises.push(uploadTask);

              uploadTask.on('state_changed', snapshot => {
              var percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
                $("#prepaImageUploadprogress").html(Math.round(percentage)+"%");
                $("#prepaImageUploadprogress").attr("style", "width:"+percentage+"%");


                }, error => { alert(error) }, () => {
                    uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => {
                        //prepaImagesUrl+="+"+downloadURL;
                       prepaImagesUrl.push(downloadURL);
                       });
}); 

问题是我得到了一个上传文件数量减一的数组(长度应该等于上传文件的数量)并且它具有相同的值(相同的下载网址) .任何帮助将不胜感激 谢谢。

【问题讨论】:

    标签: javascript firebase firebase-storage


    【解决方案1】:

    我认为问题在于承诺。我建议您使用Promise.all 并等待。因此,您的代码将更加可靠。这是我的多文件上传解决方案(适应你的变量名):

    const array = Array.from({ length: prepaImages.length }, (value, index) => index);
    const uploadedImages = await Promise.all(array.map(async index => {
      const image = prepaImages[index];
      const metadata = { contentType: image.type };
      const storageRef = firebase.storage().ref(`receipes/${category}/${title}/${uploadTime}${prepaImages[i].name}`);
      const uploadTask = storageRef.put(image, metadata);
      const url = await new Promise((resolve, reject) => {
        uploadTask.on('state_changed', snapshot => {
          const percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
          $('#prepaImageUploadprogress').html(`${Math.round(percentage)}%`);
          $('#prepaImageUploadprogress').attr('style', `width: ${percentage}%`);
        }, error => reject(error),
        async () => {
          const downloadUrl = await uploadTask.snapshot.ref.getDownloadURL();
          resolve(downloadUrl);
        });
      });
      return { name: image.name, url };
    }));
    

    uploadedImages 将包含一个包含图像名称和下载 url 的数组。当然,你可以不用等待,但我更喜欢这种方式。

    更新: 这是我自己的代码(没有错误处理)来实现这一点,另外,我需要提一下,我将它与 react、redux 和使用 firebase、firestore 包装器用于 redux redux-firestorereact-redux-firebase 但这些只是包装器:

    export const addNewWork = work => async (dispatch, getState, { getFirebase, getFirestore  }) => {
      const { files, ...restWork } = work;
      const firebase = getFirebase();
      const firestore = getFirestore();
      const storageRef = firebase.storage().ref();
      const array = Array.from({ length: files.length }, (value, index) => index);
      const uploadedFiles = await Promise.all(array.map(async index => {
        const file = files[index];
        const metadata = { contentType: file.type };
        const uploadTask = storageRef.child(`works/${file.name}`).put(file, metadata);
        const url = await new Promise((resolve, reject) => {
        uploadTask.on('state_changed', () => {}, error => reject(error), async () => {
          const downloadUrl = await uploadTask.snapshot.ref.getDownloadURL();
            resolve(downloadUrl);
          });
        });
        return { name: file.name, url };
      }));
    
      await firestore.collection('works').add({
        ...restWork,
        image: uploadedFiles[0], // Use only one image for the clean example
        createdAt: new Date()
      });
    });
    

    【讨论】:

    • 感谢您的回复。但它似乎也不起作用,它在“return { name: file.name, url };”之后返回一个空数组我试图将数组保存到数据库但它不工作,它给出了一个空数组
    • 图像来自输入字段?这个完全相同的代码在我的一个项目中运行得非常好:\
    • 也许再次检查代码,我在将变量名重命名为您的用例时犯了一些错误:\
    • 是的,是的,我已经更正了拼写错误和变量名,但是它不起作用,对于上传到数据库,我应该在“等待 Promise.all(array.map (async index => {" 或在其中,对我来说这两种情况似乎都不起作用
    • 如果可能的话,你能给我你的工作代码吗?我可以弄清楚我错过了什么
    猜你喜欢
    • 2018-10-17
    • 2020-06-24
    • 2019-11-06
    • 2020-04-08
    • 1970-01-01
    • 2020-05-17
    • 2020-04-22
    • 2011-10-12
    • 2019-08-31
    相关资源
    最近更新 更多