我正在尝试实现此代码示例此处,以将图像上传到 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
提前感谢您的指点。我一直在为此抓狂......
我遇到了这个问题,必须安装和设置代理,这样我才能看到实际的响应正文(因为 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