- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在尝试从 S3 下载文件并将该文件上传到 S3 中的另一个存储桶。 Copy API 在这里不起作用,因为我被告知不要使用它。
从 S3 获取对象有一个 response.Body
,它是一个 io.ReadCloser
并且要上传该文件,有效负载需要一个 Body
那是一个 io.ReadSeeker
。
我能解决这个问题的唯一方法是将 response.Body
保存到一个文件中,然后将该文件作为 io.ReadSeeker
传递。这需要先将整个文件写入磁盘,然后再从磁盘读取整个文件,这听起来很错误。
我想做的是:
resp, _ := conn.GetObject(&s3.GetObjectInput{Key: "bla"})
conn.PutObject(&s3.PutObjectInput{Body: resp.Body}) // resp.Body is an io.ReadCloser and the field type expects an io.ReadSeeker
问题是,我如何以最有效的方式从 io.ReadCloser
转到 io.ReadSeeker
?
最佳答案
io.ReadSeeker
是对基本 Read()
和 Seek()
方法进行分组的接口(interface)。 Seek()
方法的定义:
Seek(offset int64, whence int) (int64, error)
Seek()
方法的实现需要能够在源中查找任何地方,这要求所有源是可用或可重现。文件就是一个很好的例子,该文件被永久保存到您的磁盘中,并且可以随时读取其中的任何部分。
response.Body
被实现为从底层 TCP 连接中读取。从底层 TCP 连接中读取数据会为您提供另一端的客户端发送给您的数据。数据不会被缓存,客户端不会根据请求再次向您发送数据。这就是为什么 response.Body
没有实现 io.Seeker
(因此 io.ReadSeeker
也是如此)。
因此,为了从 io.Reader
或 io.ReadCloser
获取 io.ReadSeeker
,您需要缓存 所有数据,以便它可以根据请求搜索其中的任何位置。
这种缓存机制可能会像您提到的那样将其写入文件,或者您可以使用 ioutil.ReadAll()
将所有内容读入内存,读入 []byte
, 然后你可以使用 bytes.NewReader()
从 []byte
获取 io.ReadSeeker
。当然,这有其局限性:所有内容都必须适合内存,而且您可能不希望为该文件复制操作保留该内存量。
总而言之,io.Seeker
或 io.ReadSeeker
的实现需要所有源数据都可用,因此最好的办法是将其写入文件,或者对于将所有小文件读入 []byte
并流式传输该 byte slice 的内容。
关于go - 如何从 io.ReadCloser 转到 io.ReadSeeker?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37718191/
我是一名优秀的程序员,十分优秀!