Presigned post to aws s3 from React Native
It took a longtime to figure out how to upload images to aws s3 using presigned post from React Native.
The key part is to use FormData to construct a payload and post it with POST
http method. PUT
ing FormData payload with pre-signed URL didn’t work for me at least.
Server Side
I use Ruby on Rails for server side here. Read Direct to S3 Image Uploads in Rails | Heroku Dev Center to fully understand the code below.
FYI: You don’t need to setup CORS settings in the article for native apps.
The security model for XMLHttpRequest is different than on web as there is no concept of CORS in native apps. - https://facebook.github.io/react-native/docs/network.html
Here is the code:
# In your controller def presigned_url options = { key: "uploads/photos/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read' } presigned_post = S3_BUCKET.presigned_post(options) # FIXME: http://stackoverflow.com/a/36941996/2930161 if presigned_post render plain: { presignedPost: { fields: presigned_post.fields, url: presigned_post.url } }.to_json, status: 200, content_type: 'application/json' else render plain: { error: 'No presigned urls.' }.to_json, status: 422, content_type: 'application/json' end end
React Native
// In your component. async _uploadToS3() { try { // implement your method to fetch a presigned post object. const presignedPost = await this._fetchPreSignedPost() let formData = new FormData(); Object.keys(presignedPost.fields).forEach((key) => { formData.append(key, presignedPost.fields[key]); }); formData.append('file', { // Provide an url of a target image. uri: this.image.uri, type: 'image/jpeg', name: 'image.jpg', }) const presignedUrl = presignedPost.url fetch(presignedUrl, { method: 'POST', body: formData, headers: { 'Content-Type': 'multipart/form-data'} }) } catch (error) { console.log(error) } }
This Answer on StackOverflow inspired me for the code, thanks:
Other Links
http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Bucket.html#presigned_post-instance_method
http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/PresignedPost.html
Upload an Object Using a Pre-Signed URL (AWS SDK for Ruby) - Amazon Simple Storage Service
react-native/XHRExampleFormData.js at master · facebook/react-native · GitHub