【问题标题】:Direct uploading to AWS S3 : SignatureDoesNotMatch only for IE直接上传到 AWS S3:SignatureDoesNotMatch 仅适用于 IE
【发布时间】:2015-05-27 01:15:10
【问题描述】:

我使用 Amazon Web Service S3 上传和存储我的文件。由于这个预签名的 url,我使用 AWS Sdk 为 Node.js 服务器端生成了一个预签名的 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 向 AWS 不期望的 Content-Type 请求标头添加了一些额外的内容,这会导致签名比较出错。服务器端,Sdk 生成签名基于:

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

而当我使用 IE 调试器检查请求时,我看到了

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

在 Chrome 中我的请求标头很好

Content-Type: application/pdf

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

【问题讨论】:

  • 什么版本的IE? IE 9 及以下不支持使用 ajax 上传文件。
  • 我用 IE 11 @KevinB 测试过
  • 您是否尝试过通过 contentType 选项而不是 headers 选项设置 Content-Type 标头?
  • 是的,同样的问题。 IE 正好添加:multipart/form-data;边界=---------------7dfc53b3091c @KevinB

标签: javascript ajax node.js internet-explorer amazon-s3


【解决方案1】:

好吧,我终于想通了。

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

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

感谢this answer,我在 XMLHttpRequest 中使用原始 Javascript 来解决这个问题

var xmlHttpRequest = new XMLHttpRequest();

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

它适用于 Chrome、Firefox、IE 11(我没有测试过 IEW3Schools 它适用于 IE7+)。 IE 不再需要额外的内容类型。

希望对你有帮助

【讨论】:

    【解决方案2】:

    如果你可以访问 xhr,你可以这样做:

    var _send = xhr.send;
    xhr.send = function() {
      _send.call(xhr, file);
    }
    

    【讨论】:

      猜你喜欢
      • 2014-07-14
      • 1970-01-01
      • 2020-02-24
      • 2018-01-28
      • 2018-12-31
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      相关资源
      最近更新 更多