react-native-background-upload icon indicating copy to clipboard operation
react-native-background-upload copied to clipboard

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

Open luigbren opened this issue 4 years ago • 1 comments

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);
                      });
                  });

luigbren avatar Nov 20 '21 17:11 luigbren

@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;
  }
}

swizes avatar Nov 24 '21 10:11 swizes