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;
});
}
@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