Я видел много вопросов здесь по этой теме, но ничего, с которыми я столкнулся, не работал у меня, поэтому здесь я отправляю еще...
Я на Ruby on Rails пытается настроить загрузку файлов прямо на Amazon S3 с помощью jQuery File Upload plugin. Я пошел вместе с очень полезным учебником Heroku, чтобы начать работу с исходными настройками. Файлы загружены в порядке, но все они были помечены как Content-Type: binary/octet-stream
в S3, поэтому, когда они были представлены в приложении, все файлы загружались, а не открывались напрямую.
Это проблема, потому что я пытаюсь разрешить изображения, PDF файлы, аудио- или видеофайлы, поэтому мне нужно иметь возможность захватить правильный Content-Type
из файла и передать его на S3. При просмотре документа AWS-SDK gem на Amazon я увидел этот раздел о добавлении .where(:content_type).starts_with("")
в конец назначенного объекта post для изменения политика. Однако, когда я это сделал, он сделал ошибку:
<Error><Code>AccessDenied</Code>
<Message>Invalid according to Policy: Policy Condition failed: ["starts-with", "$Content-Type", ""]</Message>
Итак, я добавил в content_type: ""
в hash выбора для назначенного объекта post, и теперь он работает снова, но вместо всех файлов по умолчанию binary/octet-stream
все они по умолчанию равны image/jpeg
. Здесь мой код на данный момент:
контроллер
def new
@s3_direct_post = S3_BUCKET.presigned_post(
key: "uploads/#{SecureRandom.uuid}/${filename}",
success_action_status: 201,
acl: :public_read,
content_type: "").where(:content_type).starts_with("")
end
_form.html.haml
:javascript
$(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 = $("<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({
// This 'add' section is where I thought to set the Content-Type, but I've tried with and without it and Content-Type remains the same on S3
add: function (e, data) {
fd["Content-Type"] = data.files[0].type;
console.log(fd); // The JSON object shows Content-Type correctly in console
data.submit();
},
fileInput: fileInput,
url: '#{@s3_direct_post.url}',
type: 'POST',
autoUpload: true,
formData: fd, // My updated JSON object
paramName: 'file',
dataType: 'XML',
replaceFileInput: false,
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 = 'https://d295xbrl26r3ll.cloudfront.net/' + key.replace(/ /g, "%20");
// create hidden field
var input = $("<input />", { type:'hidden', name: 'item[file_url]', value: url })
form.append(input);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
});
});
Как правильно отправить Content-Type
на S3?