我正在使用内存有限的计算机上工作,我想以流方式将动态生成的(非磁盘)文件上传到S3。换句话说,开始上传时我不知道文件大小,但最后我会知道。通常,PUT请求具有Content-Length标头,但也许可以解决此问题,例如使用多部分或分块的内容类型。
S3可以支持流式上传。例如,在这里:
http://blog.odonnell.nu/posts/streaming-uploads-s3-python-and-poster/
我的问题是,在上传开始时无需指定文件长度即可完成相同的事情吗?
我正在使用内存有限的计算机上工作,我想以流方式将动态生成的(非磁盘)文件上传到S3。换句话说,开始上传时我不知道文件大小,但最后我会知道。通常,PUT请求具有Content-Length标头,但也许可以解决此问题,例如使用多部分或分块的内容类型。
S3可以支持流式上传。例如,在这里:
http://blog.odonnell.nu/posts/streaming-uploads-s3-python-and-poster/
我的问题是,在上传开始时无需指定文件长度即可完成相同的事情吗?
Answers:
您必须通过S3的multipart 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
}
}
如果您使用的是Node.js,则可以使用s3-streaming-upload之类的插件轻松完成此操作。