Skip to content

Instantly share code, notes, and snippets.

@guumaster
Last active January 23, 2023 15:48
Show Gist options
  • Star 88 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save guumaster/9f18204aca2bd6c71a24 to your computer and use it in GitHub Desktop.
Save guumaster/9f18204aca2bd6c71a24 to your computer and use it in GitHub Desktop.
How to upload a file with $.ajax to AWS S3 with a pre-signed url

Upload a file with $.ajax to AWS S3 with a pre-signed url

When you read about how to create and consume a pre-signed url on this guide, everything is really easy. You get your Postman and it works like a charm in the first run.

Then you open your browser, try your usual $.ajax() and send your PUT operation, and you hit the cold iced wall of AWS error message, a simple <Code>SignatureDoesNotMatch</Code> that will steal hours from your productivity.

So here I come to save you and give you a free working example of how to upload a file directly to AWS S3 from your browser. You are wellcome :).

var s3 = new AWS.S3({
accessKeyId: '<YOUR_ACCESS_KEY>',
secretAccessKey: '<YOUR_SECRET_ACCESS_KEY>'
});
var uploadPreSignedUrl = s3.getSignedUrl('putObject', {
Bucket: '<THE_BUCKET_NAME>',
Key: '<THE_UPLOADED_FILENAME>',
ACL: 'authenticated-read',
// This must match with your ajax contentType parameter
ContentType: 'binary/octet-stream'
/* then add all the rest of your parameters to AWS puttObect here */
});
var downloadPreSignedUrl = s3.getSignedUrl('getObject', {
Bucket: '<THE_BUCKET_NAME>',
Key: '<THE_UPLOADED_FILENAME>',
/* set a fixed type, or calculate your mime type from the file extension */
ResponseContentType: 'image/jpeg'
/* and all the rest of your parameters to AWS getObect here */
});
// now you have both urls
console.log( uploadPreSignedUrl, downloadPreSignedUrl );
<form id="theForm" method="POST" enctype="multipart/form-data" >
<input id="theFile" name="file" type="file"/>
<button id="theButton" type="submit">send 1</button>
</form>
After you uploaded the file you can <a href="<YOUR_PRE_SIGNED_DOWNLOAD_URL_HERE>">download it here</a>
<script src="upload.js"></script>
// Remember to include jQuery somewhere.
$(function() {
$('#theForm').on('submit', sendFile);
});
function sendFile(e) {
e.preventDefault();
// get the reference to the actual file in the input
var theFormFile = $('#theFile').get()[0].files[0];
$.ajax({
type: 'PUT',
url: "<YOUR_PRE_SIGNED_UPLOAD_URL_HERE>",
// Content type must much with the parameter you signed your URL with
contentType: 'binary/octet-stream',
// this flag is important, if not set, it will try to send data as a form
processData: false,
// the actual file is sent raw
data: theFormFile
})
.success(function() {
alert('File uploaded');
})
.error(function() {
alert('File NOT uploaded');
console.log( arguments);
});
return false;
});
}
@jhulford
Copy link

Thanks for this...most other docs I saw didn't include the part about the Content-Type header needing to be the same in the upload headers and the presign params. While that makes sense, it's not immediately obvious that that's the cause of the SignatureDoesNotMatch errors.

@dudyn5ky1
Copy link

Add signatureVersion: 'v4' to 01-backend-url-generation.js.

@ishansan38
Copy link

Hi. I tried this solution. Though it says "File Uploaded", my Bucket is Still Empty. Can you help me solve this ?
I tried the URL with postman, upload works, but not via this

@schermannj
Copy link

That was very helpful, you have saved a lot of my time, thanks a lot!

@anshuraj
Copy link

anshuraj commented Sep 6, 2017

Thanks a lot. This was very helpful.

@marcucio
Copy link

thanks, definitely helped!

@prabhat04011998
Copy link

prabhat04011998 commented Feb 18, 2018

with uploadPresignedurl can i access the bucket or uploaded file.
<Error> <Code>InvalidRequest</Code> <Message> The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256. </Message> <RequestId>##################</RequestId> <HostId> ############################################</HostId> </Error>

this error is showed when i click on the url showed in the console.

@ChrisGrigg
Copy link

ChrisGrigg commented Feb 26, 2018

Hi, this solution worked well for me until I started testing with lots of different PDF's. Some PDF's fail silently to upload. Any ideas on why this could be? My code's quite similar only difference is I'm generating pre-signed urls on the client.

** EDIT ** I worked out it was failing with files that had an uppercase ".PDF"

@MidnightJava
Copy link

Thanks for the explanation. In case anyone gets a CORS failure when running this code in a browser rendering a page outside of the aws domain, you have to configure your S3 service to allow CORS requests.
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/cors.html
This just configures the server to accept the request. You also have to configure the S3 bucket permissions for uploading files.

@Hirra
Copy link

Hirra commented Sep 7, 2018

Great post..kudos for the processData:false

@phanikumar1210
Copy link

I have an issue with file upload. I am good with uploading it through curl command but not with ajax call any recommendations.

@brydavis
Copy link

Got this to work after some finessing... Main issues I ran into were correctly enabling CORS and making sure may backend signature / settings (e.g. mime type, ACL) matched my subsequent PUT request with the file (hence, I kept receiving the SignatureDoesNotMatch error)

@arswaw
Copy link

arswaw commented Nov 13, 2018

Hey I wanted to let you know @guumaster that this gist really helped me solve a problem internally with uploading .zip files. I was using blobs and the File API, and it turned out that the solution was just to send the file object direct.

Thank you.

@sevenCS7
Copy link

Thanks a lot. This was very helpful.

@twfahey1
Copy link

Perfect, thank you so much for posting.

@blacksandsolutions
Copy link

Pointed me in the right direction, thanks.

@psuhas
Copy link

psuhas commented Jan 26, 2021

Thank you , very helpful

@abraaoogle
Copy link

Thank you , very helpful :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment