这将是一篇很长的文章,但是由于我不知道哪里出了问题,我认为最好是过于冗长而不是忽略基本信息。
我正在尝试按照以下指南将图像上传到我的Amazon S3存储桶:https://devcenter.heroku.com/articles/s3-upload-python。
我将代码设置如下:
index.html
<img id="preview" src="https://via.placeholder.com/320?text=Image+Upload">
<input id="file_input" class="form-control" type="file" name="image" accept="image/*">
<form method="POST" action="/gallery/upload" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="lVE...ASG">
<input type="hidden" id="image-url" name="image-url">
<input class="form-control" type="text" name="title" placeholder="Title">
<input class="form-control" type="text" name="price" placeholder="Price">
<div class="form-control">
<input type="checkbox" name="archive" value="True">
<label for="archive">Archive</label>
</div>
<input class="form-control btn-primary" type="submit">
</form>
s3.js
function uploadFile(file, s3Data, url) {
var xhr = new XMLHttpRequest();
xhr.open("POST", s3Data.url);
var postData = new FormData();
for (key in s3Data.fields) {
postData.append(key, s3Data.fields[key]);
}
postData.append('file', file);
for (var [key, value] of postData.entries()) {
console.log(key + ': ' + value);
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200 || xhr.status === 204) {
document.getElementById("preview").src = url;
document.getElementById("image-url").value = url;
}
else {
alert("Could not upload file.");
}
}
};
xhr.send(postData);
}
function getSignedRequest(file) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/gallery/sign_s3?file_name="
+ file.name + "&file_type=" + file.type);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
uploadFile(file, response.data, response.url);
}
else {
alert("Could not get signed URL.");
}
}
};
xhr.send();
}
$(document).ready(function () {
(function () {
document.getElementById("file_input").onchange = function () {
var files = document.getElementById("file_input").files;
var file = files[0];
if (!file) {
return alert("No file selected.");
}
getSignedRequest(file);
};
})();
});
views.py
S3_BUCKET = os.environ.get('S3_BUCKET')
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
s3 = boto3.client(
's3',
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
)
def sign_s3(request):
file_name = request.GET.get('file_name')
file_type = request.GET.get('file_type')
presigned_post = s3.generate_presigned_post(
Bucket=S3_BUCKET,
Key=file_name,
Fields={"acl": "public-read", "Content-Type": file_type},
Conditions=[
{"acl": "public-read"},
{"Content-Type": file_type}
],
ExpiresIn=3600
)
return JsonResponse({
'data': presigned_post,
'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
})
当我使用文件上传器选择图片时,我收到一条警告消息:“无法上传文件”,以及来自Chrome开发者控制台的以下输出:
acl: public-read
Content-Type: image/jpeg
key: dragon.jpg
x-amz-algorithm: AWS4-HMAC-SHA256
x-amz-credential: AKI...TRA/20190224/us-east-2/s3/aws4_request
x-amz-date: 20190224T044659Z
policy: eyJ...XX0=
x-amz-signature: 7ea...18a
file: [object File]
似乎已经完成了预签名,但是我从上传中得到了该XML作为响应:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>5D1...AB5</RequestId>
<HostId>cYX...WKw=</HostId>
</Error>
我的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>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
我尝试编辑存储桶策略,但仍然出现“访问被拒绝”错误。该指南没什么用:https://aws.amazon.com/premiumsupport/knowledge-center/s3-access-denied-bucket-policy/
我不知道是什么原因造成的,但是我猜是某个地方存在权限问题。我不知道在哪里任何帮助表示赞赏。
修改:用户的政策为AdministratorAccess
和AmazonS3FullAccess
。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
编辑2:通过取消选中“公共访问设置”中的“阻止新的公共存储桶策略”,我可以对存储桶策略进行更改。将其设置为以下值不再导致“存储桶策略”页面上出现“访问被拒绝”错误消息,但是我仍然无法通过XHR上传文件:
{
"Id": "Policy...237",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt...935",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::coolwater-creations/*",
"Principal": {
"AWS": [
"...764"
]
}
}
]
}
答案 0 :(得分:0)
我怀疑您使用的帐户与您在IAM中看到的帐户不同:
在您共享的屏幕截图中,您会注意到IAM用户名在屏幕截图中与您的用户名不匹配
如果您以该IAM用户身份登录,则应该在用户名中看到相同的名称
因此您要么以root帐户身份登录,在这种情况下,错误将出在创建存储桶的方式上(请检查https://aws.amazon.com/premiumsupport/knowledge-center/s3-troubleshoot-403/) 或者您使用的是AWS合作伙伴的SSO登录,在这种情况下,您在其中的权限会有所不同,并且不受您在那里看到的IAM的控制。