在内存中读取搜索器

abo*_*nec 1 go

我编写了一个下载图像的服务,通过 zip 存档加入它并将其上传回 aws。这项服务应该是省时的。我的第一个版本非常简单:

  1. 并行下载所有文件并保存到磁盘。
  2. 从磁盘读取所有文件,通过zip包加入并保存回磁盘
  3. 从磁盘读取存档并将其发送到 s3。

但我认为所有这些从磁盘操作中保存和读取的性能都低于内存通信。

我一起加入了下载和存档(所有下载阅读器都直接进入存档器)。但我不明白如何与上传者一起加入。

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)