CORS上传文件到S3,出现SignatureDoesNotMatch错误

时间:2018-04-10 03:50:32

标签: javascript amazon-web-services amazon-s3 cors

我想将视频文件从浏览器上传到S3。 这是我的步骤:

  1. 向API网关发送GET请求,调用Lambda以获取签名网址。
  2. 使用签名网址直接使用PUT将文件上传到S3。
  3. 第1步工作正常,我可以使用签名网址通过curl上传文件:

    curl -X PUT https://bucket-name.s3.amazonaws.com/testupload/videofile.mp4?AWSAccessKeyId=MY_AWS_ACCESS_KEY_ID&Expires=1523329853&Signature=XXXXX -T videophile.mp4
    

    但是从浏览器上传文件到S3,我得到403响应SignatureDoesNotMatch错误:

      

    <错误>

         

    <代码> SignatureDoesNotMatch< /代码>

         

    < Message>我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。< / Message>

         

    < AWSAccessKeyId> MY_AWS_ACCESS_KEY_ID< / AWSAccessKeyId>

         

    ...

         

    ...

         

    < /错误>

    我检查了访问密钥是我在lambda中用来创建签名网址的访问密钥

    客户端Javascript:

    $.ajax({
        url : signedurl,
        type : "PUT",
        data : uploadfile,
        dataType : "text",
        cache : false,
        contentType : file.type,
        processData : false
    })
    .done(function() {
    
    })
    .fail(function(e) {
        console.error(e.status, e.statusText)
        console.error(e.responseText)
    });
    

    Bucket CORS config:

    <?xml version="1.0" encoding="UTF-8"?>
    <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">    
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    </CORSConfiguration>
    

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。创建签名URL时和http请求标头中需要Content Type(即使您可以按curl上传文件):

Lambda代码(节点):

s3.getSignedUrl('putObject', {
    Bucket: "bucket-name",
    Key: `key/filename.ext`,
    ContentType: event.contentType,  // e.g.: "video/mp4"
    Expires: 300
})

客户端JavaScript

$.ajax({
    url : signedurl,
    type : "PUT",
    data : uploadfile,
    cache : false,
    headers:{
        'Content-Type': file.type  // e.g.: "video/mp4"
    },
    processData : false
})

有用的链接: