我正在尝试使用米切尔·桥本提供的goamz叉提供的PutPart方法。遗憾的是,每次我取回一个部件并检查它的大小,它似乎认为它是整个文件的大小,而不仅仅是一块。
例如
当上传一个15米的文件时,我希望看到
Uploading...
Processing 1 part of 3 and uploaded 5242880.0 bytes.
Processing 2 part of 3 and uploaded 5242880.0 bytes.
Processing 3 part of 3 and uploaded 5242880.0 bytes.相反,我看到:
Uploading...
Processing 1 part of 3 and uploaded 15728640 bytes.
Processing 2 part of 3 and uploaded 15728640 bytes.
Processing 3 part of 3 and uploaded 15728640 bytes.这是由于file.Read(partBuffer)的问题吗?任何帮助都将不胜感激。
我在mac上使用go 1.5.1。
package main
import (
"bufio"
"fmt"
"math"
"net/http"
"os"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/s3"
)
func check(err error) {
if err != nil {
panic(err)
}
}
func main() {
fmt.Println("Test")
auth, err := aws.GetAuth("XXXXX", "XXXXXXXXXX")
check(err)
client := s3.New(auth, aws.USWest2)
b := s3.Bucket{
S3: client,
Name: "some-bucket",
}
fileToBeUploaded := "testfile"
file, err := os.Open(fileToBeUploaded)
check(err)
defer file.Close()
fileInfo, _ := file.Stat()
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
// read into buffer
buffer := bufio.NewReader(file)
_, err = buffer.Read(bytes)
check(err)
filetype := http.DetectContentType(bytes)
// set up for multipart upload
multi, err := b.InitMulti("/"+fileToBeUploaded, filetype, s3.ACL("bucket-owner-read"))
check(err)
const fileChunk = 5242880 // 5MB
totalPartsNum := uint64(math.Ceil(float64(fileSize) / float64(fileChunk)))
parts := []s3.Part{}
fmt.Println("Uploading...")
for i := uint64(1); i < totalPartsNum; i++ {
partSize := int(math.Min(fileChunk, float64(fileSize-int64(i*fileChunk))))
partBuffer := make([]byte, partSize)
_, err := file.Read(partBuffer)
check(err)
part, err := multi.PutPart(int(i), file) // write to S3 bucket part by part
check(err)
fmt.Printf("Processing %d part of %d and uploaded %d bytes.\n ", int(i), int(totalPartsNum), int(part.Size))
parts = append(parts, part)
}
err = multi.Complete(parts)
check(err)
fmt.Println("\n\nPutPart upload completed")
}发布于 2016-01-13 03:36:40
这里的问题可能是由于没有完整地读取文件而引起的。Read可能有点微妙:
读取到len( p )字节到p。它返回读取的字节数(0 <= n <= len(p))和遇到的任何错误。即使Read返回n< len(p),它也可能在调用期间使用所有的p作为划痕空间。如果某些数据是可用的,而不是len(p)字节,那么常规读取将返回可用的数据,而不是等待更多的数据。
因此,您可能应该使用ioReadFull或(更好的) io.CopyN。
也就是说,我认为你应该尝试切换到正式的AWS Go包。他们有一个方便的上传器,可以为您处理所有这些:
package main
import (
"log"
"os"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
func main() {
bucketName := "test-bucket"
keyName := "test-key"
file, err := os.Open("example")
if err != nil {
log.Fatalln(err)
}
defer file.Close()
sess := session.New()
uploader := s3manager.NewUploader(sess)
// Perform an upload.
result, err := uploader.Upload(&s3manager.UploadInput{
Bucket: &bucketName,
Key: &keyName,
Body: file,
})
if err != nil {
log.Fatalln(err)
}
log.Println(result)
}您可以找到关于godoc.org的更多文档。
发布于 2016-01-13 03:45:47
您在partBuffer中读取的数据根本没有使用。将file传递到multi.PutPart中,它读取file的全部内容,在必要时将其查找回最初,并将您所做的所有工作都吹走。
对代码的最小更改是将bytes.NewReader(partBuffer)传递到PutPart,而不是file。bytes.Reader实现PutPart需要的io.ReadSeeker接口,并将其大小报告为partBuffer。
另一种选择是使用io.SectionReader类型--而不是自己将数据读入缓冲区,而是创建一系列基于file的SectionReader,其中包含所需的大小和偏移量,并将它们传递给PutPart,然后将读取传递给底层文件读取器。这应该同样有效,并且大大减少了您必须编写的代码(以及错误检查)。它还避免不必要地缓冲RAM中的整块数据。
发布于 2017-06-11 06:17:40
当您将文件部分传递给multi.PutPart方法(n,multi.PutPart (""))时,您的代码必须更改一些点才能正常工作,下面的代码将正常工作。
记住PutPart发送部分多部分上传,读取r中的所有内容,除最后一个部分外,每个部分的大小必须至少为5MB。它被描述在戈姆兹的文档中。
我已经更改为正确的工作点:
这里,我使用文件的所有字节创建我们的headerPart
HeaderPart:= strings.NewReader (字符串(字节))
在这里,io.ReadFull (HeaderPart,partBuffer)我正在读取make ([]字节,partSize)命令的整个缓冲区部分,每次它位于文件的某个部分。
当我们运行multi.PutPart (int (i) +1,strings.NewReader (string (PartBuffer)时,我们必须要+1,因为它不计算第0部分,而不是传递对象文件,而是使用strings.NewReader函数传递部分内容。
检查了下面的代码,它现在正常工作了。
package main
import(
"bufio"
"fmt"
"math"
"net/http"
"os"
"launchpad.net/goamz/aws"
"launchpad.net/goamz/s3"
)
func check(err error) {
if err != nil {
panic(err)
}
}
func main() {
fmt.Println("Test")
auth := aws.Auth{
AccessKey: "xxxxxxxxxxx", // change this to yours
SecretKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
}
client := s3.New(auth, aws.USWest2)
b := s3.Bucket{
S3: client,
Name: "some-bucket",
}
fileToBeUploaded := "testfile"
file, err := os.Open(fileToBeUploaded)
check(err)
defer file.Close()
fileInfo, _ := file.Stat()
fileSize := fileInfo.Size()
bytes := make([]byte, fileSize)
// read into buffer
buffer := bufio.NewReader(file)
_, err = buffer.Read(bytes)
check(err)
filetype := http.DetectContentType(bytes)
// set up for multipart upload
multi, err := b.InitMulti("/"+fileToBeUploaded, filetype, s3.ACL("bucket-owner-read"))
check(err)
const fileChunk = 5242880 // 5MB
totalPartsNum := uint64(math.Ceil(float64(fileSize) / float64(fileChunk)))
parts := []s3.Part{}
fmt.Println("Uploading...")
HeaderPart := strings.NewReader(string(bytes))
for i := uint64(0); i < totalPartsNum; i++ {
partSize := int(math.Min(fileChunk, float64(fileSize-int64(i*fileChunk))))
partBuffer := make([]byte, partSize)
n , errx := io.ReadFull(HeaderPart, partBuffer)
check(errx)
part, err := multi.PutPart(int(i)+1, strings.NewReader(string(partBuffer))) // write to S3 bucket part by part
check(err)
fmt.Printf("Processing %d part of %d and uploaded %d bytes.\n ", int(i), int(totalPartsNum), int(n))
parts = append(parts, part)
}
err = multi.Complete(parts)
check(err)
fmt.Println("\n\nPutPart upload completed")
}https://stackoverflow.com/questions/34690518
复制相似问题