Responsive Self-loading on S3 with assigned URL

Do not attempt to upload an image to S3 from React Native using a pre-signed URL. Here is my code:

create a pre-signed url in node:

const s3 = new aws.S3(); const s3Params = { Bucket: bucket, Key: fileName, Expires: 60, ContentType: 'image/jpeg', ACL: 'public-read' }; return s3.getSignedUrl('putObject', s3Params); 

here is the RN request for S3:

 var file = { uri: game.pictureToSubmitUri, type: 'image/jpeg', name: 'image.jpg', }; const xhr = new XMLHttpRequest(); var body = new FormData(); body.append('file', file); xhr.open('PUT', signedRequest); xhr.onreadystatechange = () => { if(xhr.readyState === 4){ if(xhr.status === 200){ alert('Posted!'); } else{ alert('Could not upload file.'); } } }; xhr.send(body); 

game.pictureToSubmitUri = assets-library://asset/asset.JPG?id=A282A2C5-31C8-489F-9652-7D3BD5A1FAA4&ext=JPG

signedRequest = https://my-bucket.s3-us-west-1.amazonaws.com/8bd2d4b9-3206-4bff-944d-e06f872d8be3?AWSAccessKeyId=AKIAIOLHQY4GAXN26FOQ&Content-Type=image%2Fjpeg&Expires=1465671117&Signature=bkQIp5lgzuYrt2vyl7rqpCXPcps%3D&x-amz-acl=public-read

Error message:

 <Code>SignatureDoesNotMatch</Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> 

I can successfully twist and portray on S3 using the generated URL, and I seem to be able to successfully send request.in request from RN (however, I can only see the source data on requestb.in, so I'm not 100% sure that the image is correct there).

Based on this, I narrowed my problem down to 1) my image is loading the period incorrectly or 2) somehow the way S3 wants my request to be different from how it arrives.

Any help would be appreciated muuuuuucchhhh!

UPDATE

It can successfully send from RN to S3 if the body is just text ({'data': 'foo'}). Perhaps AWS does not like mutliform data? How can I send as soon as a file in RN ???

+7
amazon-s3 amazon-web-services react-native pre-signed-url
source share
1 answer

FormData will create a multipart/form-data request. The S3 PUT object requires its request body to be a file.

You just need to send your file to the request body without wrapping it in 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. Also make sure the Content-Type header matches the signed request for the URL.

+8
source share

All Articles