我编写了一个下载图像的服务,通过 zip 存档加入它并将其上传回 aws。这项服务应该是省时的。我的第一个版本非常简单:
但我认为所有这些从磁盘操作中保存和读取的性能都低于内存通信。
我一起加入了下载和存档(所有下载阅读器都直接进入存档器)。但我不明白如何与上传者一起加入。
S3 上传器需要一个ReadSeeker来放置对象。归档器的当前实现是:
func Archive(inputQueue <-chan Input) io.ReadSeeker {
zipFile, err := os.Create("test_arch.zip")
if log.Error(err) {
os.Exit(1)
}
arch := zip.NewWriter(zipFile)
go func() {
defer arch.Close()
for input := range inputQueue {
header := &zip.FileHeader{
Name: filepath.Join(baseDir, input.Path()),
Method: zip.Store,
}
writer, err := arch.CreateHeader(header)
if log.Error(err){
os.Exit(1)
}
_, err = io.Copy(writer, input.Reader())
}
}()
return zipFile
}
Run Code Online (Sandbox Code Playgroud)
它将存档保存到磁盘。如何写archihve到中间结构通过这种结构,S3上传的是需要一个ReadSeeker?
小智 5
如果可能,您应该使用s3manager.Uploader.Uploadfrom"github.com/aws/aws-sdk-go/service/s3/s3manager"包,它接受io.Readerfor 输入并为您处理所有分段上传逻辑(这就是io.Seeker接口所需要的)。
如果这不是一个选项,您可以使用 abytes.Buffer作为io.Writer替代文件,然后使用 abytes.Reader作为io.ReadSeeker.
例如
func Archive(inputQueue <-chan Input) *bytes.Buffer {
buf := bytes.NewBuffer(nil)
arch := zip.NewWriter(buf)
go func() {
defer arch.Close()
for input := range inputQueue {
header := &zip.FileHeader{
Name: filepath.Join(baseDir, input.Path()),
Method: zip.Store,
}
writer, err := arch.CreateHeader(header)
if log.Error(err) {
os.Exit(1)
}
_, err = io.Copy(writer, input.Reader())
}
}()
return buf
}
Run Code Online (Sandbox Code Playgroud)
然后将缓冲区字节包装在 a 中bytes.Reader:
readSeeker := bytes.NewReader(buf.Bytes())
Run Code Online (Sandbox Code Playgroud)