如何在 S3 中保存数据流? aws-sdk-go 示例不起作用?
How to save data streams in S3? aws-sdk-go example not working?
我正在尝试将给定的数据流保存到 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() or client.PutObjectStreaming() 尝试过 minio-go。
这是功能性的,但消耗的内存与要存储的数据一样多。
- 有更好的解决方案吗?
- 是否有可以将任意数据通过管道传输到 S3 的小示例程序?
您可以使用 sdk 的 Uploader 来处理未知大小的上传,但您需要将 os.Stdin
"unseekable" 包装成 io.Reader
。这是因为 Uploader
,虽然它只需要一个 io.Reader
作为输入主体,但在引擎盖下它会检查输入主体是否也是 Seeker
,如果是,它确实调用了 Seek
。由于 os.Stdin
只是实现 Seeker
接口的 *os.File
,默认情况下,您会得到与从 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
更好的解决方案我不知道,你必须自己测试。
我正在尝试将给定的数据流保存到 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() or client.PutObjectStreaming() 尝试过 minio-go。 这是功能性的,但消耗的内存与要存储的数据一样多。
- 有更好的解决方案吗?
- 是否有可以将任意数据通过管道传输到 S3 的小示例程序?
您可以使用 sdk 的 Uploader 来处理未知大小的上传,但您需要将 os.Stdin
"unseekable" 包装成 io.Reader
。这是因为 Uploader
,虽然它只需要一个 io.Reader
作为输入主体,但在引擎盖下它会检查输入主体是否也是 Seeker
,如果是,它确实调用了 Seek
。由于 os.Stdin
只是实现 Seeker
接口的 *os.File
,默认情况下,您会得到与从 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
更好的解决方案我不知道,你必须自己测试。