After spending way too much time figuring out how to upload stuff (like videos and photos) to S3 in React Native with modules written by others (like react-native-uploader or react-native-fs), I decided to fall back to the good old XMLHttpRequest
.
Also this is not strictly related to React Native as it can be used anywhere, but it’s where I used recently.
I am using a couple of variables here:
presignedUrl
is the destination URL I get from our API (it is a really long string that looks something like the URL I’m putting at the bottom)
filePath
is the full path to the file (including file://).
fileType
is the mime type of the file (like video/mp4, or image/jpeg).
fileName
is the file name with extension (something.jpg).
And then, drumroll, the super simple code snippet:
const xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { // Successfully uploaded the file. } else { // The file could not be uploaded. } } } xhr.open('PUT', presignedUrl) xhr.setRequestHeader('X-Amz-ACL', 'public-read') xhr.setRequestHeader('Content-Type', fileType) xhr.send({ uri: filePath, type: fileType, name: fileName })
Presigned URL example (the bold parts vary):
https://s3.amazonaws.com/your-app-name/fileName?X-Amz-Expires=86400&X-Amz-Date=20160825T222851Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=your-credentials/date/your-server/s3/aws4_request&X-Amz-SignedHeaders=content-type;host;x-amz-acl&X-Amz-Signature=generated_signature
Note that the API is signing 3 things when generating the URL (the content-type;host;x-amz-acl
part in the url above) which I must include as headers in the request (the xhr.setRequestHeader
part). If I don’t, or if the signature doesn’t match the request headers, S3 will reject my file.
References:
http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
How do you get the response after a successful request?
I tried uploading a file, I got “xhr.status” equal to 200, but “xhr.response” seems to be empty
hi there,
thank you for posting this, I tried to upload with this way and found the file uploaded to S3 is quite different from the original file, any idea why’s that?
Regards
Hao
working great !!
[…] source: http://blog.rudikovac.com/react-native-upload-any-file-to-s3-with-a-presigned-url/ […]