【问题标题】:Golang upload Http request FormFile to Amazon S3Golang 上传 Http 请求 FormFile 到 Amazon S3
【发布时间】:2015-08-22 03:34:34
【问题描述】:

我正在创建一个微服务来处理上传到 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)
  }
}

问题是存储在S3中的文件都损坏了,经过小验证,文件payload似乎没有被读取为字节

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

【问题讨论】:

  • 对于社区知识,为什么这个问题会收到负面评价?它提出了一个明确的问题,有足够的代码,以及看似正确的 ref 标签。为 Q 和 A 为我 +1..

标签: amazon-web-services go amazon-s3


【解决方案1】:

使用ioutil.ReadAll:

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

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

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

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

ioutil.ReadAll 通过一遍又一遍地调用Read 来填充动态扩展的缓冲区,直到它到达文件末尾。 (所以也不需要bufio.Reader

此外,Put 函数会在处理大文件时出现问题(使用 ReadAll 意味着整个文件必须适合内存),因此您可能希望使用 PutReader 代替:

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

【讨论】:

  • 两种解决方案保存文件的内容长度为0,当我尝试将文件写入本地存储时,我可以读取它的内容
猜你喜欢
  • 2016-04-01
  • 2015-03-09
  • 1970-01-01
  • 2013-10-08
  • 2016-02-26
  • 1970-01-01
  • 2019-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多