загрузить несколько файлов для хранения Firebase - PullRequest
2 голосов
/ 27 марта 2019

Я работаю над приложением для Android, где Firebase - это серверная часть, мне нужно загрузить несколько изображений рецепта в хранилище Firebase, а затем сохранить загрузочный файл в базе данных 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);
                       });
}); 

проблема в том, что я получаю массив длины числа загруженных файлов минус один (длина должна быть равна количеству загруженных файлов), и он имеет то же значение (то же самое downloadurl).любая помощь будет оценена Спасибо.

1 Ответ

2 голосов
/ 27 марта 2019

Я думаю, что проблема с обещаниями. Я предлагаю вам использовать 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-адресами для загрузки. Вы можете сделать это без ожидания, конечно, но я предпочитаю этот путь.

UPDATE: Вот мой собственный код (без обработки ошибок), также я должен упомянуть, что я использую это с реакцией, редуксом и использую firebase, оболочку firestore для redux redux-firestore и react-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()
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...