15

标题说明了一切。这是我的代码;

我正在对文件使用 node-formidable。

form.on("end",function(field, file){
        params.Body = fs.createReadStream(params.filePath)
        delete params.filePath;
        S3.getSignedUrl('putObject',params, function(err, url) {
            if(err){console.log(err);}
            console.log(url);
        });
    })

上传成功后,url变量返回s3 url,类似这样;

https://bucket-name.s3.amazonaws.com/746575308_8c081369df.jpg?AWSAccessKeyId=[key]&Expires=[date]&Signature=[signature]&x-amz-acl=public-read

但仍然收到 SignatureDoesNotMatch 错误。在描述中说

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

这是我的参数

params = {
    Bucket:"bucketname",
    Key: file.name,
    ACL: 'public-read'
}

我错过了什么?

4

3 回答 3

18

我在使用服务器端时遇到了同样的问题S3.getSignedUrl('putObject',然后尝试使用该 url 客户端。

在我的案例中,我注意到可能与您的案例相关的是,使用所有这些创建的签名都S3.getSignedUrl考虑了请求标头。因此,如果您正在生成一个 URL,它将失败并显示您收到的相同错误消息,除非使用相同的标头发送。

一个失败的例子:像这样生成..

var params = { Bucket: 'YourBucket', Key: 'uniqueFileKey', Expires: 10000 };
s3.getSignedUrl('putObject', params, function (err, url) {
      if(err){
        return cb(err);
      }
      return cb(null, url)
    });

当生成使用相同的 url 时,以下请求失败。此请求是从浏览器发出的。

RequestMethod: Put
Headers: {
    Accept:*/*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.9
    Connection:keep-alive
    Content-Length:11768
    Content-Type:application/x-www-form-urlencoded; charset=UTF-8
}

不同之处在于上面创建的签名不包括内容类型,其中请求确实指定了内容类型。参数需要匹配头部,否则抛出的错误将是签名不匹配。

成功示例如下:

var params = { Bucket: 'YourBucket', Key: 'uniqueFileKey', Expires: 10000, ContentType: 'application/x-www-form-urlencoded; charset=UTF-8' };
s3.getSignedUrl('putObject', params, function (err, url) {
      if(err){
        return cb(err);
      }
      return cb(null, url)
    });
于 2018-02-20T16:19:26.447 回答
0

我遇到了同样的问题。farrellw 的回答解释了原因。

在您的情况下,您应该在客户端请求中添加带有值“ public-read ”的标头“ x-amz-acl ”。因为您在服务器上进行预签名时使用“public-read”指定了“ACL”。

您可以参考https://aboutweb.dev/blog/signaturedoesnotmatch-s3-direct-upload/了解更多详情

于 2022-02-10T03:57:37.673 回答
-4

试试这个。您需要上传对象,然后针对现有对象生成签名的 url。

var s3bucket = 'somebucket';
var s3Key = '/some/key',
var body = fs.createReadStream('/some/local/file.txt');

var params = {
    Bucket: s3bucket,
    Key: s3Key,
    Body: body
};
s3.upload(params, function(err) {
    if (err) {
        cb_1(err);
    } else {
        var params = {
            Bucket: s3bucket,
            Key: s3Key,
            Expires: parseInt(ttl)
        };
        s3.getSignedUrl('getObject', params, function(err, url) {
            if (err) {
                console.log(err);
            } else {
                console.log(err);
            }
        });
    }
});
于 2016-08-24T20:47:03.853 回答