我正在尝试将给定的数据流保存到S3兼容存储中。 在流结束之前,大小是未知的,可以从5MB到500GB不等。
我尝试了不同的可能性,但没有找到比自己实现分片更好的解决方案。我最好的猜测是使用我的流填充一个固定大小的缓冲区并将其写入S3。 有更好的解决方案吗?也许这种方式对我来说是透明的,而不是将整个流写入内存?
aws-sdk-go自述文件有一个示例程序,它从stdin获取数据并将其写入S3:https://github.com/aws/aws-sdk-go#using-the-go-sdk
当我尝试使用管道|
管道数据时,我收到以下错误:
failed to upload object, SerializationError: failed to compute request body size
caused by: seek /dev/stdin: illegal seek
我做错了什么或示例不按照我的预期工作?
我虽然尝试使用PutObject()或client.PutObjectStreaming()进行minio-go。 这是有用的,但消耗的内存与要存储的数据一样多。
答案 0 :(得分:6)
您可以使用sdk' Uploader处理未知大小的上传,但您需要让os.Stdin
"无法搜索"将其包装成io.Reader
。这是因为Uploader
虽然它只需要一个io.Reader
作为输入体,但它会检查输入体是否也是Seeker
,如果它是,它会调用Seek
。由于os.Stdin
只是实现*os.File
接口的Seeker
,因此默认情况下,您会从PutObjectWithContext
获得相同的错误。
Uploader
还允许您以可以配置其大小的块上传数据,还可以配置应同时上载这些块的数量。
这是链接示例的修改版本,剥离了可以保持不变的代码。
package main
import (
// ...
"io"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
type reader struct {
r io.Reader
}
func (r *reader) Read(p []byte) (int, error) {
return r.r.Read(p)
}
func main() {
// ... parse flags
sess := session.Must(session.NewSession())
uploader := s3manager.NewUploader(sess, func(u *s3manager.Uploader) {
u.PartSize = 20 << 20 // 20MB
// ... more configuration
})
// ... context stuff
_, err := uploader.UploadWithContext(ctx, &s3manager.UploadInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: &reader{os.Stdin},
})
// ... handle error
}
至于这是否是一个比我不知道的minio-go
更好的解决方案,你必须自己测试一下。