簡體   English   中英

直接上傳到 AWS S3 : SignatureDoesNotMatch 僅適用於 IE

[英]Direct uploading to AWS S3 : SignatureDoesNotMatch only for IE

我使用 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 向 Content-Type 請求標頭添加了一些 AWS 不期望的額外內容,這會導致簽名比較中出現錯誤。 服務器端,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?

好吧,我終於想通了。

使用 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、Firefox、IE 11(我沒有使用 IE<11 進行測試,但根據W3Schools它適用於 IE7+)。 IE 不再有額外的內容類型。

希望這可以幫助

如果您有權訪問 xhr,您可以執行以下操作:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM