这个问题已经被问到here但是这个答案对我没有帮助,因为我知道网址是正确的,因为它指向美国标准网址,详见亚马逊指南here < / p>
所以我试图通过角度库 ng-file-upload 将文件上传到我的存储桶。我相信我已经正确设置了桶:
此CORS配置:
<?xml version="1.0" encoding="UTF-8"?>
< CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
< CORSRule>
< AllowedOrigin>*</AllowedOrigin>
< AllowedMethod>POST</AllowedMethod>
< AllowedHeader>*</AllowedHeader>
< /CORSRule>
< /CORSConfiguration>
我必须在上面的开口括号后放一个空格,因为如果我不这样做,我就不会添加它。
我已经理解为从任何位置允许POSTS而不管标题 - 这是正确的吗?
我制定的政策:
{
"Version": "2012-10-17",
"Id": "Policy<numbers>",
"Statement": [
{
"Sid": "Stmt<numbers>",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::ac.testing/*"
}
]
}
最后 - 在我尝试上传的实际代码中:
var policy = {
"expiration": "2020-01-01T00:00:00Z",
"conditions": [
{"bucket": "ac.testing"},
["starts-with", "$key", ""],
{"acl": "private"},
["starts-with", "$Content-Type", ""],
["starts-with", "$filename", ""],
["content-length-range", 0, 524288000]
]
}
var uploadDetails = {
url: 'https://ac.testing.s3.amazonaws.com/',
method: 'POST',
data: {
key: file.name,
acl: 'public-read',
// application/octet-stream is the default format used by S3
'Content-Type': file.type != '' ? file.type : 'application/octet-stream',
AWSAccessKeyId: '<my-access-key-id>',
policy: policy,
signature: '<my-access-signature>',
filename: file.name,
},
file: file
};
if (file) {
// Upload to Amazon S3
file.upload = Upload.upload(uploadDetails).then(function(success) {
console.log(JSON.stringify(success) );
},function(error) {
console.log(error);
},function(progress) {
console.log(JSON.stringify(progress) );
});
}
那我在哪里错了?
编辑
我没有做的一些事情是根据Base64编码对策略和签名进行编码。
该过程涉及对策略进行编码,然后使用生成的代码以及AWS Secret Access Key生成SHA-1 HMAC代码。即使在此之后它仍然会返回相同的错误。
我还为存储桶添加了另一个权限。它匹配此处已定义的策略和CORS设置,但定义为每个人:
编辑2
我创建了一个名为 ac-k24-uploads 的新存储桶,并更新了与此匹配的网址:
uploadDetails = {
url: 'https://ac-k24-uploads.s3.amazonaws.com/',
现在出现的错误是:
编辑3
环顾四周似乎亚马逊不喜欢的标题被添加到请求中。我尝试在ng-file-uploads上运行,但是在我自己的机器上却没有。对此的修复似乎是删除这些标题:
method: 'POST',
headers: {
'Authorization': undefined
},
但我仍然得到同样的错误。为什么这些标题会附加到此请求?
编辑4
即使上面的代码仍然在不同的位置添加标题,所以我找到它并删除它们。我现在收到的错误是:
答案 0 :(得分:8)
这与CORS无关。
这是因为您的桶名称中的点。
如果你的存储桶确实符合美国标准(example-bucket.s3.amazonaws.com
不一定是&#34;美国标准&#34;网址),那么这就是你需要的:
var uploadDetails = { 网址:&#39; https://s3.amazonaws.com/ac.testing/&#39;, ...
这称为基于路径或路径样式的URL,其中存储区表示为路径的第一个元素,而不是将其包含在主机名中。
如果存储桶名称有一个点,则必须这样做;对于不在美国标准中的存储桶,s3.
需要s3-region.
。
这是通配符SSL / TLS证书的限制。 S3提供了对*.s3[-region].amazonaws.com
有效的证书,并且此类证书的规则规定*
不能匹配点...因此证书被认为是无效的,因此它是&#39;是一个不安全的回应。&#34;
或者,只需使用短划线而不是点创建一个存储桶,您的代码应该按原样运行。
由于您使用的是Signature V2,因此主机名构造会为其他相同的请求生成相同的签名。 Sig V4不适用。
答案 1 :(得分:1)
实际问题有两个:
标题不正确为&#34; 授权&#34;即使从代码的Upload.upload部分删除它,标题仍然存在。 为了解决这个问题,我不得不从我的api.injector代码中删除该对象 - 这就是它被添加的地方。
delete config.headers['Authorization']
从EDIT3开始,我生成的签名是错误的 - 所以我不得不重新生成它。
感谢迈克尔的帮助。