Vydia / react-native-background-upload

Upload files in your React Native app even while it's backgrounded. Supports Android and iOS, including camera roll assets.
MIT License
730 stars 333 forks source link

help to upload several photos one by one with map function and keep the array order #292

Open luigbren opened 2 years ago

luigbren commented 2 years ago

good day, I am using eact-native-background-upload to upload the images, the problem is that when I send the publication all the photos are sent at the same time in random order, I need to configure to upload the files one by one, I leave the example of how I'm working...

how can I make .map go through the cycle, wait for Upload.startUpload to finish uploading the file and then continue .map with the next item in the array, it should be noted that I have already tried placing (await Upload.startUpload) but it does not work anyway .map goes through the whole array and all the files are uploaded at the same time, completely changing the position of the images in the array.

                  this.state.arichiUpload.map((i, idx) => {
                    let file = i.uri;
                    if (Platform.OS == 'android') {
                      file = i.uri.replace('file://', '');
                    }

                    Upload.startUpload({
                      url:
                        this.conex + 'pub.php?f=regmediapost',
                      path: file,
                      method: 'POST',
                      field: 'file',
                      type: 'multipart',
                      parameters: {
                        ......
                        ......
                      },
                      maxRetries: 2,
                      headers: {
                        'content-type': 'multipart/form-data',
                        Accept: 'application/json',
                      },
                      notification: {
                        enabled: true,
                        //autoClear: false,
                        notificationChannel: 'UploadMedia',
                      },
                      useUtf8Charset: true,
                    })
                      .then(uploadId => {
                        Upload.addListener('progress', uploadId, data => {
                          //console.log(`Progress: ${data.progress}%`);
                        });
                        Upload.addListener('error', uploadId, data => {
                          //console.log(`Error: ${data.error}%`);
                        });
                        Upload.addListener('cancelled', uploadId, data => {
                          //console.log(`Cancelled!`);
                        });
                        Upload.addListener('completed', uploadId, data => {
                          //console.log('Completed!');
                        });
                      })
                      .catch(err => {
                        //console.log('Upload error!', err);
                      });
                  });
swizes commented 2 years ago

@luigbren

You need to wrap this Upload function with a promise, so you can "await" the result of the current upload

Check https://www.digitalocean.com/community/tutorials/js-async-functions

I explain what I did.

Created a file called backgroundUploadUtils.js

In this file I have only one function

export const backgroundFileUpload = ({file, tempPostId}) => {
  return new Promise(function (resolve, reject) {
    const options = {
      url: 'yourUploadURL',
      path: 'fileURI',
      method: 'POST',
      field: 'file',
      type: 'multipart',
      parameters: {
        //....
      },
      maxRetries: 2,
      headers: {
        'content-type': 'multipart/form-data',
      },
      notification: {
        enabled: true,
        //....
      },
      useUtf8Charset: true,
    };

    Upload.startUpload(options)
      .then(uploadId => {
        console.log('Upload started');
        Upload.addListener('progress', uploadId, data => {
          //console.log(`Progress: ${data.progress}%`);
        });
        Upload.addListener('error', uploadId, data => {
          console.log(`Error: ${data.error}%`, data);
          reject({status: false, data: 'Error'});
        });
        Upload.addListener('cancelled', uploadId, data => {
          //console.log('Cancelled!', data);
          reject({status: false, data: 'Cancelled'});
        });
        Upload.addListener('completed', uploadId, data => {
          // data includes responseCode: number and responseBody: Object
          console.log('Completed!', data);

          if (data.responseCode !== 200) {
            reject({status: false, data: 'Response code is not  ok'});
          } else {
            resolve({status: true, data: 'Response code is ok'});
          }
        });
      })
      .catch(err => {
        console.log('Upload error!', err);
        reject({status: false, data: err});
      });
  });
};

And I call that function from a loop

for (const file of files) {
  const uploaded = await backgroundFileUpload({
    file,
    someData: {x: 'y'},
  }).then(res => {
    return res.status;
  });

  if (!uploaded) {
    //One upload has failed so we exit the loop
    return;
  }
}