我正在创建一个微服务来处理一些上传到 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 中的文件都已损坏,经过少量验证后似乎文件负载不是按字节读取的
如何将文件转换为字节并正确存储到S3?
最佳答案
使用ioutil.ReadAll
:
bs, err := ioutil.ReadAll(file)
// ...
err = bucket.Put(
header.Filename,
bs,
header.Header.Get("Content-Type"),
s3.ACL("public-read"),
)
Read
是一个具有微妙行为的低级函数:
Read reads data into p. It returns the number of bytes read into p. It calls Read at most once on the underlying Reader, hence n may be less than len(p). At EOF, the count will be zero and err will be 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"),
)
关于amazon-web-services - Golang上传Http请求FormFile到Amazon S3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32152005/