react-native: [Android] FormData does not support data URIs

React Native version: Expo 33 / React Native 0.59.8

Steps To Reproduce

  1. Call formData.append with a data URI as the uri
  2. Make XHR request and send FormData
const dataUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=';
const formData = new FormData();
formData.append('file', {
  name: 'myfile',
  type: 'image/png',
  uri: dataUri,
});

const request = new XMLHttpRequest();
request.open('POST', 'http://httpbin.org/post');
request.onreadystatechange = function() {
  if (request.readyState === 4) {
    if (request.status === 200) {
      console.log("SUCCESS")
      // will succeed on iOS
    } else {
      console.log(request.responseText);
      // response on Android will be "Could not retrieve file for uri data:image/png;base64,iVBO..."
    }
  }
};
request.send(formData);

Describe what you expected to happen:

The request would succeed (as it does on iOS) but instead (on Android only), you get this error:

Could not retrieve file for uri data:image/png;base64,iVB…

Snack: https://snack.expo.io/@maxholderc5/cd0ef5

It appears that the Android implementation assumes this will always be a file, but unless I’ve misunderstood, passing a data URI here should also be valid (at least, it seems to work on iOS).

A workaround for my specific scenario (in case it is helpful for others running into this) was to write a temporary file and provide its filepath instead of the data URI directly, e.g. with Expo:

const tempFileDirectory = `${FileSystem.cacheDirectory}uploadTmp`
await FileSystem.makeDirectoryAsync(tempFileDirectory, { intermediates: true })
const tempFilePath = `${tempFileDirectory}${Date.now()}.png`
const base64EncodedData = dataUri.split(',')[1]
await FileSystem.writeAsStringAsync(tempFilePath, base64EncodedData, {
  encoding: FileSystem.EncodingType.Base64,
})
// ...
formData.append(name, {
  name: "myfile",
  type: "image/png",
  uri: tempFilePath,
})
// ...
await FileSystem.deleteAsync(tempFilePath)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 13
  • Comments: 25 (1 by maintainers)

Most upvoted comments

I’ll work on this issue

This is still an issue

This is still an issue

This is still an issue 😕

This is still an issue

This is still an issue

This is still an issue