Presigned AWS S3 PUT url无法使用jquery从客户端上传

时间:2021-01-12 10:45:40

Just started working with the node.js aws client to generate a presigned url and send it to the browser for the user to upload the file, but I get the following message:

刚开始使用node.js aws客户端生成预签名URL并将其发送到浏览器以供用户上传文件,但我收到以下消息:

SignatureDoesNotMatch The request signature we calculated does not match the signature you provided. Check your key and signing method.

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

I have references quite a few links and it seems really basic, but I seem to be failing

我引用了很多链接,看起来很基本,但我似乎失败了

https://github.com/aws/aws-sdk-js/issues/251

https://github.com/aws/aws-sdk-js/issues/251

Direct Browser Upload to S3 with Meteor, jQuery and the AWS SDK

直接浏览器使用Meteor,jQuery和AWS SDK上传到S3

https://forums.aws.amazon.com/thread.jspa?messageID=556839

https://forums.aws.amazon.com/thread.jspa?messageID=556839

Either, I am completely stupid or the sdk is really difficult to use

要么,我完全是愚蠢的,或者sdk真的很难用

node:

节点:

var putParams = {
      Bucket: config.aws.s3UploadBucket,
      Key: filename,
      ACL: 'public-read',
      Expires: 120,
      Body: '',
      ContentMD5: 'false'
    };
s3.getSignedUrl('putObject', putParams, function (err, url) {
  if (!!err) {
    console.error(err);
    res.json({error: ''});
    return;
  }

  res.json({
    'awsAccessKeyId': config.aws.accessKeyId,
    's3bucket': config.aws.s3UploadBucket,
    's3key': filename,
    's3policy': s3policy.policy,
    's3signature': s3policy.signature,
    'url': url
  });
});

client:

客户:

  var fd = new FormData();
      fd.append('file', file);
    return new RSVP.Promise(function(resolve, reject) {
            $.ajax({
              url: uploadObj.url,
              data: fd,
              processData: false,
              contentType: false,
              crossDomain: true,
              type: 'PUT',
              success: function(json, textStatus, jqXhr){
                console.log(json);
                resolve(json);
              },
              error: function(jqXhr, textStatus, errorThrown){
                reject({ jqXhr: jqXhr, textStatus: textStatus, errorThrown: errorThrown});
              }
            });
          });

UPDATE: In response to some of the comments, I did put in a valid CORS for the bucket.

更新:为了回应一些评论,我确实为该桶提供了有效的CORS。

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

3 个解决方案

#1


4  

I've been fighting this as well. This is what worked for me and I was getting the exact same error as you.

我也一直在打这个。这对我有用,我得到了与你完全相同的错误。

On the server side, I'm using AWS-SDK for nodejs

在服务器端,我正在使用AWS-SDK作为nodejs

var params = {
    Bucket: "bucketname",
    Key: "filename", 
    ContentType: "multipart/form-data"
}
var url = s3.getSignedUrl('putObject', params, function(err, url) { 
    console.log(url);
}

Client Side

客户端

$.ajax({
    method: "PUT",
    headers: {"Content-Type": "multipart/form-data"},
    processData: false,
    url: "http://AWSURL?AWSAccessKeyId..."
})

Your cors looks right to me, the key was ensuring that the headers for Content-Type matched exactly

你的cors看起来对我来说,关键在于确保Content-Type的标题完全匹配

#2


0  

I had the same problem but I don't remember exactly what the problem was but this answer may help you upload-file-from-angularjs-directly-to-amazon-s3-using-signed-url.

我有同样的问题,但我不记得究竟是什么问题,但这个答案可以帮助你上传文件从angularjs-direct-to-amazon-s3-using-signed-url。

Server:

服务器:

var AWS = require('aws-sdk');

AWS.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey:     AWS_SECRET_KEY});
AWS.config.region = 'eu-west-1';

app.post('/s', function (req, res) {
    var s3 = new AWS.S3();
    var params = {Bucket: 'BUCKETNAME', Key: req.body.name, ContentType: req.body.type};
    s3.getSignedUrl('putObject', params, function(err, url) {
        if(err) console.log(err);
        res.json({url: url});
    });
});

Client:

客户:

$.ajax({
    url: '/s',
    type: 'POST',
    data: {name: file.name, size: file.size, type:file.type},
}).success(function(res){
    $.ajax({
        url: res.url,
        type: 'PUT',
        data: file,
        processData: false,
        contentType: file.type,
    }).success(function(res){
        console.log('Done');
    });

#3


0  

Thanks a ton to jeremy and kungfoo! I was having the same issues, though an added wrinkle when using Python's boto library. If you're generating the URLs from Python, a minimum working config seems to be:

非常感谢jeremy和kungfoo!虽然在使用Python的boto库时增加了皱纹,但我遇到了同样的问题。如果您从Python生成URL,则最小工作配置似乎是:

Python

Boto3 works but not Boto2!

Boto3有效但不是Boto2!

import boto3
conn = boto3.client('s3', ...)
url = conn.generate_presigned_url('put_object', {
    'Bucket': my_bucket_name,
    'Key': my_bucket_key,
    'ContentType': 'my_content_type'
}, 300)

S3 (CORS)

The minimum required rules seem to be:

所需的最低规则似乎是:

<CORSRule>
    <AllowedOrigin>*.mydomain.com</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Content-*</AllowedHeader>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>

Client

Using jQuery, and being sure to keep the same content type as before:

使用jQuery,并确保保持与以前相同的内容类型:

$.ajax({
    type: "PUT",
    headers: {"Content-Type": "my_content_type"},
    url: url_from_server,
    data: my_data_as_string,
    processData: false,
    contentType: false,
    crossDomain: true,
    cache: false
});

#1


4  

I've been fighting this as well. This is what worked for me and I was getting the exact same error as you.

我也一直在打这个。这对我有用,我得到了与你完全相同的错误。

On the server side, I'm using AWS-SDK for nodejs

在服务器端,我正在使用AWS-SDK作为nodejs

var params = {
    Bucket: "bucketname",
    Key: "filename", 
    ContentType: "multipart/form-data"
}
var url = s3.getSignedUrl('putObject', params, function(err, url) { 
    console.log(url);
}

Client Side

客户端

$.ajax({
    method: "PUT",
    headers: {"Content-Type": "multipart/form-data"},
    processData: false,
    url: "http://AWSURL?AWSAccessKeyId..."
})

Your cors looks right to me, the key was ensuring that the headers for Content-Type matched exactly

你的cors看起来对我来说,关键在于确保Content-Type的标题完全匹配

#2


0  

I had the same problem but I don't remember exactly what the problem was but this answer may help you upload-file-from-angularjs-directly-to-amazon-s3-using-signed-url.

我有同样的问题,但我不记得究竟是什么问题,但这个答案可以帮助你上传文件从angularjs-direct-to-amazon-s3-using-signed-url。

Server:

服务器:

var AWS = require('aws-sdk');

AWS.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey:     AWS_SECRET_KEY});
AWS.config.region = 'eu-west-1';

app.post('/s', function (req, res) {
    var s3 = new AWS.S3();
    var params = {Bucket: 'BUCKETNAME', Key: req.body.name, ContentType: req.body.type};
    s3.getSignedUrl('putObject', params, function(err, url) {
        if(err) console.log(err);
        res.json({url: url});
    });
});

Client:

客户:

$.ajax({
    url: '/s',
    type: 'POST',
    data: {name: file.name, size: file.size, type:file.type},
}).success(function(res){
    $.ajax({
        url: res.url,
        type: 'PUT',
        data: file,
        processData: false,
        contentType: file.type,
    }).success(function(res){
        console.log('Done');
    });

#3


0  

Thanks a ton to jeremy and kungfoo! I was having the same issues, though an added wrinkle when using Python's boto library. If you're generating the URLs from Python, a minimum working config seems to be:

非常感谢jeremy和kungfoo!虽然在使用Python的boto库时增加了皱纹,但我遇到了同样的问题。如果您从Python生成URL,则最小工作配置似乎是:

Python

Boto3 works but not Boto2!

Boto3有效但不是Boto2!

import boto3
conn = boto3.client('s3', ...)
url = conn.generate_presigned_url('put_object', {
    'Bucket': my_bucket_name,
    'Key': my_bucket_key,
    'ContentType': 'my_content_type'
}, 300)

S3 (CORS)

The minimum required rules seem to be:

所需的最低规则似乎是:

<CORSRule>
    <AllowedOrigin>*.mydomain.com</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Content-*</AllowedHeader>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>

Client

Using jQuery, and being sure to keep the same content type as before:

使用jQuery,并确保保持与以前相同的内容类型:

$.ajax({
    type: "PUT",
    headers: {"Content-Type": "my_content_type"},
    url: url_from_server,
    data: my_data_as_string,
    processData: false,
    contentType: false,
    crossDomain: true,
    cache: false
});