React-dropzone 从客户端上传到 S3 返回 400 错误请求

问题描述 投票:0回答:1

我正在尝试实现此代码示例此处,以将图像上传到 S3 存储桶。 我的服务器似乎返回了预签名 URL,但随后的 PUT 请求失败并出现 400 错误。

这是服务器端预签名代码:

var s3 = new aws.S3();

    var params = {
        Bucket: secrets.aws.bucket,
        Key: body.filename,
        ContentType: body.filetype,
        ACL: 'public-read'

    };

    s3.getSignedUrl('putObject', params, function(err, data) {
        if (err) {
            console.log(err);
            return err;
        } else {
          console.log('URL sent back to client ------------------------------------');
            res.status(200).send(data);
        }
    });

这是客户端的上传操作:

export function uploadFile(data) {

  var file = data[0];

  return dispatch => {
    dispatch(dropFileAccepted(data));

    return makeUploadRequest('post', {filename: file.name, filetype: file.type}, '/signURLforS3')

        .then(function (result) {
            var signedUrl = result.data;

            var options = {
              headers: {
                'Content-Type': file.type,
                'x-amz-acl': 'public-read',
                'x-amz-region': 'eu-central-1'
              }
            };
          return axios.put(signedUrl, file, options);
        })
        .then(function (result) {
          console.log(result);
        })
        .catch(function (err) {
          console.log(err);
        });
  };
} 

从网络请求/响应标头来看,存储桶上的内容类型和 CORS 配置似乎已正确设置,但我不确定是否存在需要设置区域的问题。 或者我是否需要在存储桶上进行一些其他设置,例如存储桶策略,或指定签名版本?

Request URL:https://XXXXXXXXXX.s3.amazonaws.com/brand.png?AWSAccessKeyId=AKXXXXXXXXXXXX&Content-Type=image%2Fpng&Expires=1460128516&Signature=%2BooCHlrwelBYC9fMYnu01PokgWM%3D&x-amz-acl=public-read
Request Method:PUT
Status Code:400 Bad Request
Remote Address:54.231.192.36:443 

Response Headers
Access-Control-Allow-Methods:PUT, POST, GET, HEAD
Access-Control-Allow-Origin:*
Access-Control-Max-Age:3000
Connection:close
Content-Type:application/xml
Date:Fri, 08 Apr 2016 15:00:17 GMT
Server:AmazonS3
Transfer-Encoding:chunked
Vary:Origin, Access-Control-Request-Headers, Access-Control-Request-Method
x-amz-id-2:rXMCu6YD5mLrN3beBCs+kmXDGzhzrQHV2fTUTNooWXBQuPfLNOKDcArGQWRj+NLk+zo=
x-amz-region:eu-central-1
x-amz-request-id:FC181ED154

Request Headers
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,fr-FR;q=0.2,fr;q=0.2
Connection:keep-alive
Content-Length:16819
Content-Type:image/png
Host:XXXXXXX.s3.amazonaws.com
Origin:http://localhost:3000
Referer:http://localhost:3000/admin/blog/create
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
x-amz-acl:public-read
x-amz-region:eu-central-1

Query String Params
AWSAccessKeyId:AKXXXXXXXX
Content-Type:image/png
Expires:1460128516
Signature:+ooCHlrwelBYu01PokgWM=
x-amz-acl:public-read

提前感谢您的指点。我一直在为此抓狂......

amazon-s3 aws-sdk
1个回答
0
投票

我遇到了这个问题,必须安装和设置代理,这样我才能看到实际的响应正文(因为 Chrome 不会向您显示它)。我遇到的问题是

react-dropzone-s3-uploader
默认为上传到 S3 添加标头,即:

x-amz-acl: public

如果您想要公开上传,这很好,但如果您在与此不匹配的上传的预签名 URL 上设置 ACL,则文件的 HTTP PUT 将出现 HTTP 400 错误,并以此作为响应body(同样,需要代理才能查看响应正文,因为 Chrome/浏览器不显示它):

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>InvalidRequest</Code>
  <Message>Conflicting values provided for argument: x-amz-acl</Message>
  <RequestId>...</RequestId>
  <HostId>...</HostId>
</Error>

解决方案是在传递到组件的

uploadRequestHeaders
属性中包含一个
upload
键,如下所示:

          upload={{
            ...
            uploadRequestHeaders: {
              'x-amz-acl': 'private',
            },
          }}

当然,将

x-amz-acl
的值设置为您想要的ACL。

参考https://github.com/Founderlab/react-dropzone-s3-uploader/blob/master/src/DropzoneS3Uploader.js#L92

© www.soinside.com 2019 - 2024. All rights reserved.