I use Amazon Web Service S3 to upload and store my files. I generate a pre signed url with AWS Sdk for Node.js server-side to upload directly files from browser thanks to this pre signed url.
How it works
Server-side I have a method wich returns the pre-signed url.
AWS.config.loadFromPath(__dirname + '/../properties/aws-config.json');
AWS.config.region = 'eu-west-1';
//Credentials are loaded
var s3 = new AWS.S3();
var docId = req.query.doc;
var params = {
Bucket: res.locals.user.bucketId,
Key: docId+"."+req.query.fileExtension,
ACL : "bucket-owner-read",
ContentType : req.query.fileType
};
s3.getSignedUrl('putObject', params, function (err, url) {
if(url){
res.writeHead(200);
var result = {
AWSUrl : url
};
//Generates pre signed URL with signature param
res.end(JSON.stringify(result));
}
}
I upload directly my file to S3 client-side
var loadToAWSS3 = function(url, file, inputFileId){
var data = new FormData();
data.append('file', file);
$.ajax({
url: url,//url getted from server-side method
type: 'PUT',
data : data,
headers: {
'Content-Type': file.type
},
processData: false,
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){
myXhr.upload.addEventListener('progress',function(e){
if(e.lengthComputable){
var max = e.total;
var current = e.loaded;
var percentage = (current * 100)/max;
//stuff to handle progress...
}
},
false);
}
return myXhr;
},
statusCode: {
200: function () {
//some stuff
}
});
}
Chrome & Firefox behaviors
Works as expected, the pre signed url is getted, then the file is uploaded, I can see it in my AWS S3 console.
Lovely IE 11
SignatureDoesNotMatch error ! IE add some extra stuff to Content-Type request header not expected by AWS which causes error in the signature comparison. Server-side, the Sdk generates signature based on :
ContentType : req.query.fileType //(something like application/pdf)
whereas when I inspect the request with IE debugger, I see
Content-Type application/pdf, multipart/form-data; boundary=---------------------------7df2f3283091c
in Chrome my request header is fine
Content-Type: application/pdf
What can I do to remove this IE extra Content-Type ? If not possible, how can I generate this extra stuff before sending the request in order to get the pre-signed url with the extra stuff in the signature ?
OK, I finally figured it out.
Using FormData() simulates that you are sending files through a form. That's why IE always adds
multipart/form-data; boundary=---------------------------7**********
To get around the problem I use raw Javascript with XMLHttpRequest thanks to this answer
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open('PUT', url, true);
xmlHttpRequest.setRequestHeader('Content-Type', file.type);
xmlHttpRequest.send(file);
And it works with Chrome, Firefox, IE 11 (I have not tested with IE<11 but according to W3Schools it works for IE7+). No more extra content type with IE.
Hope this helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With