直接上传到AWS S3:SignatureDoesNotMatch仅适用于IE

我使用Amazon Web Service S3上传和存储我的文件。 我使用AWS Sdk for Node.js服务器端生成预先签名的url,以便直接从浏览器上传文件,这要归功于此预先签名的url。

怎么运行的

服务器端我有一个方法,返回预签名的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)); } } 

我直接上传我的文件到S3客户端

 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的行为

按预期运行,预先签名的URL被获取,然后文件被上传,我可以在我的AWS S3控制台中看到它。

可爱的IE 11

SignatureDoesNotMatch错误! IE添加一些额外的东西到内容types的请求标头没有预期的AWS导致签名比较错误。 在服务器端,Sdk根据以下内容生成签名:

 ContentType : req.query.fileType //(something like application/pdf) 

而当我用IEdebugging器检查请求,我看到

  Content-Type application/pdf, multipart/form-data; boundary=---------------------------7df2f3283091c 

在Chrome中,我的请求标题很好

 Content-Type: application/pdf 

我能做些什么来删除这个IE额外的内容types? 如果不可能,在发送请求之前如何生成这些额外的东西,以便在签名中获得预先签名的url和额外的东西?

好的,我终于明白了。

使用FormData()模拟你通过表单发送文件。 这就是为什么IE总是添加

 multipart/form-data; boundary=---------------------------7********** 

为了解决这个问题,我使用XMLHttpRequest的原始Javascript感谢这个答案

 var xmlHttpRequest = new XMLHttpRequest(); xmlHttpRequest.open('PUT', url, true); xmlHttpRequest.setRequestHeader('Content-Type', file.type); xmlHttpRequest.send(file); 

它适用于Chrome浏览器,火狐浏览器,IE 11(我还没有用 IE浏览器testing过,但根据W3School的说法,它可以用于IE7 +)。 与IE没有更多的额外的内容types。

希望这可以帮助