管理者が大きなファイルを Amazon S3 にアップロードする Rails 4 アプリを構築しています。大きなファイルの転送を検証するために、Amazon ドキュメントに従ってリクエスト ヘッダーに Content-MD5 フィールドを含めたいと思います。
http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
Paperclip + S3 から始めましたが、MD5 検証は機能しています。
has_attached_file :file,
:storage => :s3,
:bucket => AppSetting.s3_bucket,
:s3_credentials => Proc.new{|a| a.instance.s3_credentials },
:s3_permissions => :private,
:s3_headers => Proc.new{|a| a.s3_headers },
:path => "uploads/:id/:basename.:extension"
def s3_credentials
{:access_key_id => AppSetting.aws_access_key_id, :secret_access_key => AppSetting.aws_secret_access_key}
end
# md5sum is a value entered by the user as a string (hex notation)
# ex: "7d592a3129ab6a867cf6e2eb60f9ef83"
#
def encoded_md5sum
[[md5sum].pack("H*")].pack("m0")
end
def s3_headers
{:content_md5 => encoded_md5sum}
end
Paperclip では、まず大きなファイルがサーバーにアップロードされ、次に Amazon S3 に転送されます。これにより Rails プロセスがブロックされ、余分な帯域幅が消費されるため、S3UploadDirect gem を使用してファイルを S3 バケットに直接アップロードしようとしています。
この gem は、Railscasts エピソード 383 のコードのラッパーであり、実際のアップロードには jquery-fileupload-rails を使用します。
<%= s3_uploader_form callback_url: "#{AppSetting.host_base_url}/admin/uploads",
callback_method: "POST",
callback_param: "upload[file_url]",
key: "uploads/{timestamp}-{unique_id}-#{SecureRandom.hex}/${filename}",
key_starts_with: "uploads/",
acl: "private",
bucket: AppSetting.s3_bucket,
aws_access_key_id: AppSetting.aws_access_key_id,
aws_secret_access_key: AppSetting.aws_secret_access_key,
max_file_size: 5.gigabytes,
id: "s3-uploader",
class: "upload-form",
data: {:key => :val} do %>
<%= file_field_tag :file, multiple: true %>
<% end %>
<script id="template-upload" type="text/x-tmpl">
<div id="file-{%=o.unique_id%}" class="upload">
{%=o.name%}
<div class="progress"><div class="bar" style="width: 0%"></div></div>
</div>
</script>
ファイルをアップロードできますが、Content-MD5 情報をアップロード リクエスト ヘッダーに渡す方法がわかりません。