React Native upload to S3 with presigned URL
FormData
will create a multipart/form-data
request. S3 PUT
object needs its request body to be a file.
You just need to send your file in the request body without wrapping it into FormData
:
function uploadFile(file, signedRequest, url) {
const xhr = new XMLHttpRequest();
xhr.open('PUT', signedRequest);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if(xhr.status === 200) {
alert(url);
} else {
alert('Could not upload file.');
}
}
};
xhr.send(file);
};
See https://devcenter.heroku.com/articles/s3-upload-node for example in a browser. Please also ensure your Content-Type
header is matched with the signed URL request.
I've wasted way too much time on uploading to pre-signed S3 URL on both iOS and Android. What worked for me was rn-fetch-blob lib
Code snippet:
import RNFetchBlob from 'rn-fetch-blob'
const preSignedURL = 'pre-signed url'
const pathToImage = '/path/to/image.jpg' // without file:// scheme at the beginning
const headers = {}
RNFetchBlob.fetch('PUT', preSignedURL, headers, RNFetchBlob.wrap(pathToImage))
"rn-fetch-blob": 0.12.0,
"react-native": 0.61.5
This code works for both Android & iOS
const response = await RNFetchBlob.fetch(
'PUT',
presignedUrl,
{
'Content-Type': undefined
},
RNFetchBlob.wrap(file.path.replace('file://', '')),
)
Note
{'Content-Type': undefined}
is needed for iOS