2 回答
TA贡献1829条经验 获得超6个赞
io.ReadSeeker是分组基本Read()和Seek()方法的接口。方法的定义Seek():
Seek(offset int64, whence int) (int64, error)
该Seek()方法的实现需要能够在源中的任何位置寻找,这要求所有源都可用或可重现。文件就是一个很好的例子,该文件永久保存到您的磁盘中,并且可以随时读取其中的任何部分。
response.Body被实现为从底层 TCP 连接中读取。从底层 TCP 连接中读取数据会为您提供另一端的客户端发送给您的数据。数据不会被缓存,客户端不会根据请求再次向您发送数据。这就是为什么response.Body不实施io.Seeker(因此也不实施io.ReadSeeker)。
因此,为了io.ReadSeeker从io.Readeror中获取 an io.ReadCloser,您需要缓存所有数据的东西,以便根据请求它可以搜索到其中的任何位置。
正如您提到的,这种缓存机制可能会将其写入文件,或者您可以将所有内容读入内存,读入[]byteusing ioutil.ReadAll(),然后您可以使用bytes.NewReader()从. 当然,这有其局限性:所有内容都必须适合内存,而且您可能不想为此文件复制操作保留该内存量。io.ReadSeeker[]byte
总而言之,实现io.Seeker或io.ReadSeeker要求所有源数据都可用,因此最好的选择是将其写入文件,或者将小文件全部读入 a[]byte并流式传输该字节片的内容。
TA贡献1993条经验 获得超6个赞
作为替代方案,使用github.com/aws/aws-sdk-go/service/s3/s3manager.Uploader,它将 aio.Reader作为输入。
我想PutObject采用 anio.ReadSeeker而不是 an的原因io.Reader是对 s3 的请求需要签名(并且具有内容长度),但是在拥有所有数据之前您无法生成签名。执行此操作的流式方法是将输入缓冲到块中,并使用分段上传 api 分别上传每个块。这是(我认为)s3manager.Uploader在幕后所做的。
- 2 回答
- 0 关注
- 518 浏览
添加回答
举报
