Golang multipart上传了chunked`http.GET`和Goamz`ulti.PutAll`

时间:2014-12-25 22:50:53

标签: go goamz

我正在使用Goamz软件包,并且可以使用一些帮助来获取bucket.Multi来向S3传输HTTP GET响应。

我将通过分块HTTP下载2 GB以上的文件,我想将其直接流式传输到S3存储桶中。

似乎我需要将resp.Body包含在内,以便我可以将s3.ReaderAtSeeker的实现传递给multi.PutAll

// set up s3
auth, _ := aws.EnvAuth()
s3Con := s3.New(auth, aws.USEast)
bucket := s3Con.Bucket("bucket-name")

// make http request to URL
resp, err := http.Get(export_url)
if err != nil {
    fmt.Printf("Get error %v\n", err)
    return
}

defer resp.Body.Close()

// set up multi-part 
multi, err := bucket.InitMulti(s3Path, "text/plain", s3.Private, s3.Options{})
if err != nil {
    fmt.Printf("InitMulti error %v\n", err)
    return
}

// Need struct that implements: s3.ReaderAtSeeker
// type ReaderAtSeeker interface {
//  io.ReaderAt
//  io.ReadSeeker
// }

rs := // Question: what can i wrap `resp.Body` in?

parts, err := multi.PutAll(rs, 5120)
if err != nil {
    fmt.Printf("PutAll error %v\n", err)
    return
}

err = multi.Complete(parts)
if err != nil {
    fmt.Printf("Complete error %v\n", err)
    return
}

目前,在尝试运行程序时出现以下(预期)错误:

./main.go:50: cannot use resp.Body (type io.ReadCloser) as type s3.ReaderAtSeeker in argument to multi.PutAll:
    io.ReadCloser does not implement s3.ReaderAtSeeker (missing ReadAt method)

2 个答案:

答案 0 :(得分:1)

你没有说明你用来访问S3 api的软件包,但我假设它是这个 https://github.com/mitchellh/goamz/

由于您的文件很大,可能的解决方案可能是使用multi.PutPart。这将为您提供比multi.PutAll更多的控制权。使用标准库中的Reader,您的方法是:

  1. 从响应标题中获取Content-Length
  2. 根据Content-Length和partSize
  3. 获取所需的零件数量
  4. 循环遍历部分数量并从response.Body读取[]字节为bytes.Reader并调用multi.PutPart
  5. multi.ListParts
  6. 获取零件
  7. 调用multi.Complete with parts。
  8. 我无法访问S3,所以我无法测试我的假设,但如果你还没有,那么上述内容值得探讨。

答案 1 :(得分:0)

更简单的方法是使用 - http://github.com/minio/minio-go

它实现了PutObject(),这是一个完全托管的自包含操作,用于上传大文件。它还可以自动执行多部分并行处理超过5MB的数据。如果未指定预定义的ContentLength。它会一直上传,直到达到EOF。

以下示例显示了如何操作,当一个人没有预先定义的输入长度但是io.Reader是流式传输时。在这个例子中,我使用了" os.Stdin"作为你的分块输入的等价物。

package main

import (
    "log"
    "os"

    "github.com/minio/minio-go"
)

func main() {
    config := minio.Config{
        AccessKeyID:     "YOUR-ACCESS-KEY-HERE",
        SecretAccessKey: "YOUR-PASSWORD-HERE",
        Endpoint:        "https://s3.amazonaws.com",
    }
    s3Client, err := minio.New(config)
    if err != nil {
        log.Fatalln(err)
    }

    err = s3Client.PutObject("mybucket", "myobject", "application/octet-stream", 0, os.Stdin)
    if err != nil {
        log.Fatalln(err)
    }

}
$ echo "Hello my new-object" | go run stream-object.go