メモリが限られているマシンで作業していますが、動的に生成された(ディスクからではない)ファイルをストリーミング方式でS3にアップロードしたいと思います。つまり、アップロードを開始したときのファイルサイズはわかりませんが、終わりまでにはわかります。通常、PUT要求にはContent-Lengthヘッダーがありますが、マルチパートまたはチャンク化されたコンテンツタイプを使用するなど、おそらくこれを回避する方法があります。
S3はストリーミングアップロードをサポートできます。たとえば、こちらをご覧ください。
http://blog.odonnell.nu/posts/streaming-uploads-s3-python-and-poster/
私の質問は、アップロードの開始時にファイルの長さを指定せずに同じことを達成できますか?
S3のマルチパートAPI 経由で5MiB +チャンクでファイルをアップロードする必要があります。これらの各チャンクにはContent-Lengthが必要ですが、大量のデータ(100MiB +)をメモリにロードすることを回避できます。
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の制限は現在5TBです)。
彼の問題はあなたのものとは異なります-彼はアップロード前に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()
役に立つ場合に備えて、他の人のためにこの答えをここに入れてください:
S3までストリーミングしているデータの長さがわからない場合は、_S3FileInfo
_とそのOpenWrite()
メソッドを使用して、S3に任意のデータを書き込むことができます。
_var fileInfo = new S3FileInfo(amazonS3Client, "MyBucket", "streamed-file.txt");
using (var outputStream = fileInfo.OpenWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
streamWriter.WriteLine("Hello world");
// You can do as many writes as you want here
}
}
_
gof3r コマンドラインツールを使用して、Linuxパイプをストリーミングできます。
$ tar -czf - <my_dir/> | gof3r put --bucket <s3_bucket> --key <s3_object>
HTTPマルチパートエンティティリクエストの詳細を参照してください。ファイルをデータの塊としてターゲットに送信できます。
Node.jsを使用している場合、 s3-streaming-upload のようなプラグインを使用して、これを非常に簡単に実行できます。