Saturday 23 October 2021

Resumable uploading fails in background on Android - React Native

The following code for uploading works fine on iOS but on Android it sometimes (not everytime) returns following error because of wrong chunk size.

Example Error:

400: Invalid request. There were 1527808 byte(s) in the request body. There should have been 3145728 byte(s) (starting at offset 15728640 and ending at offset 18874367) according to the Content-Range header.

while trying to upload a chunk and keeps on returning the same error for retrying to upload the same chunk unless the whole upload is restarted.

The chunk created to upload has the right size because the values in the Content-Range header are taken from the chunk itself. According to the headers, the chunk size was as expected but it's losing data while uploading.

I noticed that this is happening when the device locks or goes in background while uploading.

I'm using RNFS to read chunks from file and RNFetchBlob for the PUT request.

function uploadChunk(offset) {

   let nextOffset = offset;
   const thisRecordingInProgress = isInProgress(); // true or false
   const totalBytes = thisRecordingInProgress ? '*' : size;  // size = actual file size

   // if no offset is specified, fetch it from the server
   if (nextOffset === undefined) {
     const res = await RNFetchBlob.fetch('PUT', url, {
       'Content-Length': '0',
       'Content-Range': `bytes */${totalBytes}`,
     });
     ({ nextOffset } = parseResponse(res));
   }
   // 1. Creating chunk
    const chunk = await RNFS.read(path, CHUNK_SIZE, nextOffset, 'base64');
    const end = nextOffset + Buffer.from(chunk, 'base64').length - 1;
    // 2. Upload request
    const resp = await RNFetchBlob.config({
            IOSBackgroundTask: true,
          })
            .fetch(
              'PUT',
              URL,
              {
                'Content-Length': `${CHUNK_SIZE}`,
                'Content-Range': `bytes ${nextOffset}-${end}/${totalBytes}`,
                'Content-Type': 'application/octet-stream',
                'Transfer-Encoding': 'Chunked',
              },
              chunk
            )
            .uploadProgress(written => {
              // track upload Progress
            });
    // 
    ({ nextOffset } = await parseResponse(resp));// parses response from server for next offset
    if (nextOffset < 0) {
      // Completed
    } else {
        // Upload next chunk
        return uploadChunk(nextOffset);
    }
}

I have tried decreasing the chunk size but the issue still persists. Is there anything I need to do enable this to work in background for android? Or any ideas what could be the issue. I would really appreciate any help I can get. Thanks

Updates:

  1. I tried removing the Content-Range as it's optional for 'Transfer-Encoding': 'Chunked' but that didn't fix.
  2. Tried unsetting chunk - chunk = undefined after the upload request completes to free up memory. Issue still not fixed.


from Resumable uploading fails in background on Android - React Native

No comments:

Post a Comment