S3に大容量ファイルを直接アップロードする(署名付きURL + マルチパートアップロード)
前回、署名付きURLを利用し、S3に対してファイルを直接アップロードできることを確認した。 この方法で、curlコマンドで大容量のファイルがアップロードできることも確認した。 ブラウザからも200MB程度のファイルをAJAXでアップロードできることを確認した。
しかし、300MBのファイルがブラウザからアップロードできず。。。 何か設定が足りていない・・・? どうやら調べていると、大容量ファイルのアップロードはマルチパートアップロードを推奨しているとのこと。
そこで、署名付きURL + マルチアップロードを試してみることにした。
目的
クライアントは署名付きURLを利用してファイルをマルチパートアップロードする
環境
構成
処理の流れ
- create_multipart_upload
- 署名付きURLの生成(ファイル分割数だけ)
- partsの取得
- complete_multipart_upload
やり方
前提として、AWSの設定は前回と同じように実施した。
1. create_multipart_upload
upload_id等を発行する。upload_idは署名付きURLを発行する際に利用する。
s3 = Aws::S3::Client.new uploader = s3.create_multipart_upload(bucket: bucket_name, key: key)
2. 署名付きURLの生成(ファイル分割数だけ)
分割してアップロードするファイルの数だけ署名付きURLを発行する。
presigner = Aws::S3::Presigner.new urls = [] (1..part_number).each do |num| urls.push( presigner.presigned_url(:upload_part, bucket: uploader.bucket, key: uploader.key, upload_id: uploader.upload_id, part_number: num))
3. partsの取得
署名付きURLでのアップロード完了後に実施する。 マルチアップロードの完了には、etagとpart_numberが必要になる。 下記コードで、マルチアップロードのpart一覧から、etagとpart_numberを取得する。
parts = [] parts_info = s3.list_parts(bucket: uploader.bucket_name, key: uploader.key, upload_id: uploader.upload_id).parts parts_info.each do |part| part_info = { etag: part.etag, part_number: part.part_number } parts.push(part_info) end
4. complete_multipart_upload
マルチアップロードを完了する。 完了させないと、ファイルはS3バケットに表示されない。
s3.complete_multipart_upload( upload_id: uploader.upload_id, multipart_upload: parts, bucket: uploader.bucket_name, key: uploader.key )