我尝试将此heroku教程(https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails)用于我的第一个应用。我花了一个星期的时间来研究这个复杂过程的细节,并且在这个过程中丢失了大部分剩余的头发。然而,在上传我的头像时设置内容类型的最后一点是剩下的。
我已尝试关注stackoverflow(Setting the Content-Type in direct to S3 upload using Rails and jQuery File Upload)上的帖子,在上传到aws之前设置文件的content_type但是当我尝试这样做时,我得到了403禁止错误。你能给些建议么。?在没有上述更改的情况下加载的默认内容类型是binary / octect-stream。
提供AWS.rb
AWS.config(access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] )
S3_BUCKET = AWS::S3.new.buckets[ENV['S3_BUCKET']]
用户控制器具有预先签名的帖子 -
@s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: 201, acl: :public_read).where(:content_type).starts_with("")
新用户表单中的脚本如下所示 -
<script>
$(function() {
$('.directUpload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<br><div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
var fd = <%= @s3_direct_post.fields.to_json.html_safe %>;
fileInput.after(barContainer);
fileInput.fileupload({
fileInput: fileInput,
url: '<%= @s3_direct_post.url %>',
type: 'POST',
autoUpload: true,
formData: fd,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
replaceFileInput: false,
limitMultiFileUploads: 1,
maxFileSize: 999000,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
progressBar.css('background', 'green').css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Uploading done");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = '//<%= @s3_direct_post.url.host %>/' + key;
// create hidden field
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
form.append(input);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
},
add: function (e, data) {
fd["Content-Type"] = data.files[0].type;
data.formData = fd;
data.submit();
}
});
});
});
</script>
我还尝试过设置aws存储桶策略失败,但这没有帮助 -
{
"Statement": [
{
"Principal": "*",
"Sid": "AllowPublicRead",
"Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:DeleteObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucket-name/*",
"arn:aws:s3:::bcuket-name"
]
}
]
}
任何指针都会有所帮助! TIA!
答案 0 :(得分:0)
如果您获得403,则意味着POST请求被拒绝。您应该为您的存储桶启用POST。
目前你不允许发布POST。我通常使用CORS配置:
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
您可能希望将原点更改为您自己的域,以防止来自其他来源的请求。
答案 1 :(得分:0)
对不起,不好意思。我想出了这个问题。对于遇到这篇文章的其他人来说,我在原帖中提供的代码应该按照没有存储桶策略的方式工作。我在测试的代码中添加了另一个:function(e,data){},并且正在进行其他文件类型检查,这是真正的罪魁祸首。
Michael - 内容类型正在添加:回调函数。
Lukasz Muzyka - 我的CORS设置相同......
非常感谢你的帮助!