1. ホーム
  2. http

S3へのファイルアップロードをcontent-lengthヘッダなしでストリーミングすることは可能ですか?

2023-09-25 03:27:54

質問

私はメモリが限られたマシンで作業しており、動的に生成された(ディスクからではない)ファイルをストリーミング方式で S3 にアップロードしたいと思っています。 言い換えれば、私はアップロードを開始するときにファイル サイズを知らないが、終了時には知っているだろう。 通常、PUTリクエストはContent-Lengthヘッダを持ちますが、おそらく、マルチパートまたはチャンクされたcontent-typeを使用するなど、これを回避する方法があるのでしょう。

S3はストリーミングアップロードをサポートすることができます。 例えば、こちらをご覧ください。

http://blog.odonnell.nu/posts/streaming-uploads-s3-python-and-poster/

質問は、アップロードの開始時にファイルの長さを指定しなくても、同じことを達成できるでしょうか。

どのように解決するのですか?

5MiB以上のファイルをアップロードするには S3のマルチパートAPI . これらの各チャンクには Content-Length が必要ですが、メモリに大量のデータ (100MiB 以上) を読み込むことを避けることができます。

  • S3を開始する マルチパートアップロード .
  • バッファがS3のチャンクサイズの下限(5MiB)に達するまで、データをバッファに集めます。バッファを構築している間にMD5チェックサムを生成します。
  • そのバッファを パート としてアップロードし、ETagを保存します(これについてはドキュメントを読んでください)。
  • データのEOFに到達したら、最後のチャンクをアップロードします(5MiBより小さくすることができます)。
  • Multipart Upload を確定します。

S3は10,000パーツまで可能です。したがって、5MiB のパーツサイズを選択することで、最大 50GiB の動的ファイルをアップロードできるようになります。ほとんどのユースケースで十分でしょう。

しかし、それ以上必要な場合は、パーツ サイズを大きくする必要があります。より大きなパーツ サイズ (たとえば 10MiB) を使用するか、アップロード中にサイズを大きくする必要があります。

First 25 parts:   5MiB (total:  125MiB)
Next 25 parts:   10MiB (total:  375MiB)
Next 25 parts:   25MiB (total:    1GiB)
Next 25 parts:   50MiB (total: 2.25GiB)
After that:     100MiB

これにより、1TBまでのファイル(S3の1ファイルの上限は現在5TB)を、不必要にメモリを消費することなくアップロードできるようになります。


あなたの は Sean O'Donnells のブログへのリンクです。 :

彼の問題は、あなたとは異なります。彼は、アップロードの前に Content-Length を知っており、それを使用しています。彼は、この状況を改善したいと考えています。多くのライブラリは、ファイルからすべてのデータをメモリにロードすることにより、アップロードを処理します。擬似コードでは、このようになります。

data = File.read(file_name)
request = new S3::PutFileRequest()
request.setHeader('Content-Length', data.size)
request.setBody(data)
request.send()

彼の解決策は Content-Length をファイルシステム API 経由で取得します。そして、ディスクからリクエストストリームにデータをストリームします。擬似コードでは

upload = new S3::PutFileRequestStream()
upload.writeHeader('Content-Length', File.getSize(file_name))
upload.flushHeader()

input = File.open(file_name, File::READONLY_FLAG)

while (data = input.read())
  input.write(data)
end

upload.flush()
upload.close()