Issues uploading image to S3 via Amplify (iOS)

Please provide the following:

  1. SDK Version: "expo": "~39.0.2", "react-native": "https://github.com/expo/react-native/archive/sdk-39.0.4.tar.gz"
  2. Platforms(Android/iOS/web/all): iOS

I’m struggling to get the result of expo-image-picker uploaded to S3 via Amplify’s Storage.put().

I believe the issue is that Storage.put() expects a Blob argument but the support for Blobs on react-native/Expo seems a bit experimental.

When I include base64: true in the ImagePicker.launchImageLibraryAsync() options it seems to pretty consistently load the result.base64 attribute successfully, i.e.

    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      //...
      base64: true,
    });

However when I pass that into Storage.put('filename', result.base64) the resulting image uploaded is completely garbled (I believe the upload encoding is simply wrong). I believe the upload type has to be a Blob.

That brings me to Blob. I’ve tried several different methods of trying to load the local file result.uri as a Blob, including:

    let picture = await fetch(result.uri);
    picture = await picture.blob();

and

const urlToBlob = (url: string) => new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onerror = reject;
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        resolve(xhr.response);
      }
    };
    xhr.open('GET', url);
    xhr.responseType = 'blob'; // convert type
    xhr.send();
  });
  //...
  const picture = await urlToBlob(result.uri);

both of these approaches seem to work intermittently but break down if they’re used more than once or if I upload a large file.

I also took a look at rn-fetch-blob but it doesn’t seem to work with Expo as it requires react-native link.

This is starting to feel like a memory leak or something. I can’t imagine why it would work consistently the first time but break down after trying to upload any additional images.

Cross-referencing some potentially related issues:

I realize the Storage.put() API may be causing issues here. I can potentially look into changing the API to use more standard fetch()/axios/etc. and upload to a signed URL, but I’m not necessarily confident that I wouldn’t just run into the same issue down the road. Some examples suggest using FormData() and appending the files but I have the suspicion that I will run into similar tomfoolery.

Alternatively, if anybody has any suggestions about an alternative image picking package that can return a Blob I would be very interested in giving it a shot.

Expo has been a dream to work with up to this point. I’m starting to feel rather frustrated. I’m considering changing my approach entirely and working on a native Swift implementation instead.

Thanks for your help!

Adding some additional links:
https://github.com/aws-amplify/amplify-js/issues/5311
https://github.com/expo/expo/issues/2402#issuecomment-443726662

Associated github issue: Expo Blob S3 upload fails on iOS (Unable to resolve data for blob) · Issue #7257 · aws-amplify/amplify-js · GitHub

I think this is what was causing the trouble const imageData = new File([picture], imageName)

1 Like

Im having exactly the same problem.
The problem seems to be when constructing the blob from the file. There hasnt been any solution that i could find for this

@frey-sw Could you share a small snippet of what you’re doing? My code is working pretty consistently now that I’m not using new File().

Is it working the first time but not on subsequent passes?

Glad you seem to have gotten to the bottom of things, @spokelse! Thanks for continuing to help others in the community as well! We love seeing that compassion from our users. :clap:

Cheers,
Adam

1 Like

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