Error when getting blob of a large video file

  1. SDK Version: 36.0.2
  2. Platforms(Android/iOS/web/all): Currently only tested in the Expo client

I’m trying to get the blob of a file in order to upload it to a server. It works great for small files, but when I try to get the blob of a large video file (500 MB) then it fails.

I’m currently using fetch in order to get the blob, e.g. fetch(imageUri). I’ve also tried building my own XMLHttpRequest but it fails with the same error.

I’ve provided the error stack for both calls below, they almost look identical. Any help solving this would be much appreciated.

The error using fetch:

Network request failed

Stack trace:
  http://127.0.0.1:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&minify=false&hot=false:181410:39 in onerror
  node_modules\event-target-shim\dist\event-target-shim.js:818:39 in EventTarget.prototype.dispatchEvent
  node_modules\react-native\Libraries\Network\XMLHttpRequest.js:574:29 in setReadyState
  node_modules\react-native\Libraries\Network\XMLHttpRequest.js:388:25 in __didCompleteResponse
  node_modules\react-native\Libraries\vendor\emitter\EventEmitter.js:190:12 in emit
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:436:47 in __callFunction
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:111:26 in __guard$argument_0
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:384:10 in __guard
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:110:17 in __guard$argument_0
  [native code]:null in callFunctionReturnFlushedQueue

The error using XMLHttpRequest:

Stack trace:
  node_modules\whatwg-fetch\dist\fetch.umd.js:473:29 in xhr.onerror
  node_modules\event-target-shim\dist\event-target-shim.js:818:39 in EventTarget.prototype.dispatchEvent
  node_modules\react-native\Libraries\Network\XMLHttpRequest.js:574:29 in setReadyState
  node_modules\react-native\Libraries\Network\XMLHttpRequest.js:388:25 in __didCompleteResponse
  node_modules\react-native\Libraries\vendor\emitter\EventEmitter.js:190:12 in emit
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:436:47 in __callFunction
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:111:26 in __guard$argument_0
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:384:10 in __guard
  node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:110:17 in __guard$argument_0
  [native code]:null in callFunctionReturnFlushedQueue

Could you please include the code you’re using to make this fetch() or XMLHttpRequest() call?

Also, what OS/device were you running the Expo client on?

I’m on Windows 10 / Dell XPS 15 laptop. This also happens in my published Android standalone app.

The code is fairly simple:

        let result = await ImagePicker.launchImageLibraryAsync({
            mediaTypes: ImagePicker.MediaTypeOptions.All,
            allowsEditing: false,
            quality: 1,
        });

        if (!result.cancelled) {
            const imageData = await fetch(result.uri) // <-- This line crashes with the error stack posted in my previous post.
        }

I’m now wondering if this could be related to Expo storing the video temporarily, and when I finally click on Upload then the file could be gone? Wouldn’t that give some kind of ‘Not found’ error instead?

Another theory is that this file is too large for the memory and needs to be chunked somehow.

Hi. I meant were you running the Expo app on an Android or iOS phone. Sorry, I didn’t notice the “platform=android” in your stack trace.

So you already have the video file on the device? What are you intending to do with it after const imageData = [...]? That fetch() call looks like you’re trying to download something rather than upload it?

I’m running the Expo client on my Android phone, Galaxy S10e. This error also occurs in the standalone app without the Expo client.

I noticed that I’ve talked about running into error in relation to getting the blob of a file, which is partly incorrect. The error occurs when I’m getting the video file on my device using fetch(). The reason I’m getting the video file with fetch(localFileUri) is because I need reference to the video blob, which is then finally uploaded to Google Drive.

Here are the steps I’m using for uploading a blob to Google Drive/Google Photos & S3:

  1. Get the video file on my device, which was picked using the ImagePicker:
    const imageData = await fetch(imageUri)
    Please note that this step crashes for large files.

  2. Get the blob from the imageData, which is dependent on step 1:
    const blob = await imageData.blob();

  3. And this is how I upload the blob to Google Drive:

    await fetch(googleDriveSignatureUrl, {
        method: 'PUT',
        body: blob,
    })
    

I hope this helps explain the issue. If there’s a better way to get access to a file blob then that might do the trick, but I haven’t found any alternative. The FileSystem lib would be an ideal candidate, but it only offers reading the file contents as a string or base64, which doesn’t work for me. Base64 would never work for a large video files.

Thanks.

Does Google Drive allow for something like this?

let formData = new FormData();
formData.append("fieldname", {
  uri: localUri,
  name: "filename",
  type: "the content type"
});
await fetch(googleDriveSignatureUrl, {
  method: "PUT",
  body: formData,
  headers: {
    "Content-Type": "multipart/form-data"
  }
});

EDIT: I’ve just found this, which is of course what you’re doing:

https://github.com/facebook/react-native/issues/11103#issuecomment-263045744

Unfortunately that seems to convert the file to base64 string, which happens behind the scenes in fetch. I’m also unsure how this will affect the performance to convert a large file > 500MB to a string.

I recall trying this without luck, but I’ll try it again later today. Blob is much more performant since it’s uploading binary instead of string.

1 Like

Is there any alternative to get the blob of a file instead of using XMLHttpRequest? Please note that fetch() uses XMLHttpRequest, which is why it results in the same error.

I’m really struggling to upload large blobs because of this issue. Wouldn’t the FileSystem API be an ideal candidate for getting the blob of a file? Or if we could get the blob returned from the ImagePicker?

I tried using the FileSystem API to load the file in chunks, but that API only offers reading file as UTF8 or Base64. When I use UTF8 it always crashes no matter what start and length I set to options. However, I’m able to fetch a few chunks using Base64, but eventually the app runs out of memory and crashes. So that method doesn’t work :frowning:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.