我正在尝试指定直接上传到S3的内容类型获得以下403错误:
根据政策无效:政策条件失败:[" start-with", " $ Content-Type",""]
我已将其他帖子中找到的所有内容都放在此处无济于事。我的代码:
配置/初始化/ aws.rb
Aws.config.update({
region: 'us-east-1',
credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']),
})
S3_BUCKET_NAME = Aws::S3::Resource.new.bucket(ENV['S3_BUCKET_NAME'])
doc_uploads_controller.rb
before_action :set_s3_direct_post
private
def set_s3_direct_post
@s3_direct_post = S3_BUCKET_NAME.presigned_post(key: "my_path/${filename}", success_action_status: '201', acl: 'authenticated-read', server_side_encryption: 'AES256', content_type_starts_with: '')
end
new.html.erb
<%= form_for(@doc_upload, url: new_doc_upload_path, html: { class: "directUpload" }, data: { 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host }) do |f| %>
<%= render 'errors', f: f %>
<%= hidden_field_tag "Content-Type", "" %>
<div class="row">
<span class="btn btn-success fileinput-button">
<span>Select File</span>
<!-- The file input field used as target for the file upload widget -->
<input id="doc_upload_file_url" type="file" name="doc_upload[file_url]">
</span>
<!-- The container for the uploaded files -->
<div id="files" class="files"></div>
<div id="progress" class="progress">
<div class="progress-bar progress-bar-success"></div>
</div>
</div>
<div class="row">
<p><%= f.button "Save", id: 'doc-upload-submit', disabled: true, data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."}, class: "btn btn-form btn-warning" %></p>
<p><%= link_to 'Cancel', doc_uploads_path, id: 'cancel-link' %></p>
</div>
<% end %>
doc_uploads.js.coffee
$(document).on 'turbolinks:load', ->
$ ->
'use strict'
url = $('.directUpload').find("input:file").parents('form:first').data('url')
formdata = $('.directUpload').find("input:file").parents('form:first').data('form-data')
uploadButton = $('<button/>')
.addClass('btn btn-default btn-upload')
.prop('type', 'button')
.prop('disabled', true)
.text('Processing...')
.on('click', ->
$('#cancel-link').hide()
$this = $(this)
data = $this.data()
$this.off('click').text('Abort').on('click', ->
$this.remove()
data.abort()
$('#cancel-link').show()
)
data.submit().always( ->
$this.remove()
)
)
$('#doc_upload_file_url').fileupload({
url: url,
type: 'POST',
autoUpload: false,
formData: formdata,
paramName: 'file',
dataType: 'XML',
replaceFileInput: false,
maxNumberOfFiles: 1,
acceptFileTypes: /(\.|\/)(jpe?g|jpg|png|pdf|doc|docx|xls|xlsx)$/i,
maxFileSize: 104857600,
uploadTemplateId: null,
downloadTemplateId: null,
dropZone: null
}).on('fileuploadadd', (e, data) ->
$('#filename').remove()
data.context = $('<div/>').prop('id', 'filename').appendTo('#files')
$.each(data.files, (index, file) ->
node = $('<p/>').append($('<span/>').text(file.name))
node.appendTo(data.context)
if (!index)
$('#filename').append(uploadButton.clone(true).data(data))
)
).on('fileuploadprocessalways', (e, data) ->
index = data.index
file = data.files[index]
$('#Content-Type').attr('value',file.type)
node = $(data.context.children()[index])
if (file.error)
node.append('<br>').append($('<span class="text-danger"/>').text(file.error))
if (index + 1 == data.files.length)
data.context.find('button').text('Upload').prop('disabled', !!data.files.error)
).on('fileuploadprogressall', (e, data) ->
progress = parseInt(data.loaded / data.total * 100, 10)
$('#progress .progress-bar').css('width',progress + '%')
).on('fileuploaddone', (e, data) ->
form = $('.directUpload').find("input:file")
key = $(data.jqXHR.responseXML).find("Key").text()
input = $("<input />", { type:'hidden', name: form.attr('name'), value: key })
form.append(input)
$('#progress .progress-bar').css('background', 'green').text("Upload Complete")
$('#doc-upload-submit').prop('disabled', false)
$('#doc-upload-submit').trigger('click')
,
).on('fileuploadfail', (e, data) ->
message = $(data.jqXHR.responseXML).find("Message").text()
$.each(data.files, (index) ->
error = $('<span class="text-danger"/>').text('File upload failed.')
$(data.context.children()[index]).append('<br>').append(error)
)
).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled')
当我从预先签名的帖子中删除content_type_starts_with:
设置时,一切正常,减去S3中内容类型的设置。在提交之前,我没有在表单中正确设置Content-Type吗?
请帮忙!
更新:我尝试用以下内容替换隐藏字段更新,但403响应仍然存在。
formdata["Content-Type"] = file.type
console.log(formdata)
data.formData = formdata
console.log(data.formData)
控制台会将结果data.formData
显示为:
{key: "uploads/1/${filename}", success_action_status: "201", acl: "authenticated-read", x-amz-server-side-encryption: "AES256", policy: "eyJleHBpcmF0aW9uIjoiMjAxNy0xMi0xMVQwNDo1Mzo1NFoiLC…seyJ4LWFtei1kYXRlIjoiMjAxNzEyMTFUMDM1MzU0WiJ9XX0=", …}
Content-Type: "application/pdf"
acl: "authenticated-read"
key: "my_path/${filename}"
policy: "eyJleHBpcmF0aW9uIjoiMjAxNy0xMi0xMVQwNDo1Mzo1NFoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJlZy1zdGFnaW5nLXVwbG9hZHMifSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVwbG9hZHMvMS8iXSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwMSJ9LHsiYWNsIjoiYXV0aGVudGljYXRlZC1yZWFkIn0seyJ4LWFtei1zZXJ2ZXItc2lkZS1lbmNyeXB0aW9uIjoiQUVTMjU2In0sWyJzdGFydHMtd2l0aCIsIiRDb250ZW50LVR5cGUiLCIiXSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSURKNE1LRjdMTlA3RDZLUS8yMDE3MTIxMS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0seyJ4LWFtei1hbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJ4LWFtei1kYXRlIjoiMjAxNzEyMTFUMDM1MzU0WiJ9XX0="
success_action_status: "201"
x-amz-algorithm: "AWS4-HMAC-SHA256"
x-amz-credential: "[redacted]"
x-amz-date: "20171211T035354Z"
x-amz-server-side-encryption: "AES256"
x-amz-signature:"[redacted]"
__proto__:Object
答案 0 :(得分:0)
您需要在formData上设置Content-Type,而不是在隐藏字段中设置。
而不是:
$('#Content-Type').attr('value',file.type)
尝试:
formdata["Content-Type"] = file.type
data.formData = formdata
这对我有用,但我一次只上传一个文件。由于您要上传多个内容,如果它们有不同的内容类型,这可能无效,但值得一试。
更新:这里的代码对我有用,但请记住它直接自动上传到S3,所以它可能与你正在做的不同,但希望它有所帮助。
# @s3ResumeFields came from @s3_direct_post.fields
formData = @s3ResumeFields
resumeInput.fileupload
fileInput: resumeInput,
url: @s3ResumeUrl, # this came from @s3_direct_post.url
type: 'POST',
autoUpload: true,
formData: formData,
paramName: 'file',
dataType: 'XML',
replaceFileInput: false
add: (e, data) ->
formData["Content-Type"] = data.files[0].type
data.formData = formData
data.submit()
progressall: (e, data) ->
# unrelated UI updates to show progress
start: (e) ->
# unrelated UI updates to show progress
done: (e, data) ->
# unrelated UI updates to notify that the upload completed
fail: (e, data) ->
# unrelated UI updates to show upload failed