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 ???