Golang将Http请求FormFile上传到Amazon S3

Ham*_*mza 3 amazon-s3 go amazon-web-services

我正在创建一个微服务来处理一些附件上传到Amazon S3,我想要实现的是接受一个文件,然后将它直接存储到我的Amazon S3存储桶,我当前的功能:

func upload_handler(w http.ResponseWriter, r *http.Request) {
  file, header, err := r.FormFile("attachment")

  if err != nil {
    fmt.Fprintln(w, err)
    return
  }

  defer file.Close()

  fileSize, err := file.Seek(0, 2) //2 = from end
    if err != nil {
         panic(err)
    }

    fmt.Println("File size : ", fileSize)

  bytes := make([]byte, fileSize)
  // read into buffer
  buffer := bufio.NewReader(file)
  _, err = buffer.Read(bytes)

  auth := aws.Auth{
        AccessKey: "XXXXXXXXXXX",
        SecretKey: "SECRET_KEY_HERE",
  }
  client := s3.New(auth, aws.EUWest)
  bucket := client.Bucket("attachments")

  err = bucket.Put(header.Filename, bytes, header.Header.Get("Content-Type"), s3.ACL("public-read"))

  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是存储在S3中的文件都已损坏,经过小的验证后,文件有效负载似乎不会被读取为字节

如何将文件转换为字节并将其正确存储到S3?

Cal*_*leb 6

用途ioutil.ReadAll:

bs, err := ioutil.ReadAll(file)
// ...
err = bucket.Put(
    header.Filename, 
    bs, 
    header.Header.Get("Content-Type"), 
    s3.ACL("public-read"),
)
Run Code Online (Sandbox Code Playgroud)

Read 是一个具有微妙行为的低级函数:

读取将数据读入p.它返回读入p的字节数.它在底层Reader上最多调用一次,因此n可能小于len(p).在EOF,计数将为零,错误将为io.EOF.

所以可能发生的事情是文件数据的某些子集被写入S3以及一堆0.

ioutil.ReadAll通过Read一遍又一遍地调用填充动态扩展缓冲区直到它到达文件末尾为止.(所以没有必要bufio.Reader)

Put函数也会出现大文件问题(使用ReadAll意味着整个文件必须适合内存),所以你可能想要使用PutReader:

bucket.PutReader(
    header.Filename, 
    file, 
    fileSize, 
    header.Header.Get("Content-Type"), 
    s3.ACL("public-read"),
)
Run Code Online (Sandbox Code Playgroud)