亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用 Go 跟蹤分段上傳到 s3 的進度?

如何使用 Go 跟蹤分段上傳到 s3 的進度?

Go
滄海一幻覺 2021-12-06 19:53:20
我正在嘗試使用 Mitchell Hashimoto 的 goamz fork 提供的 PutPart 方法??杀氖牵看挝胰』匾徊糠植z查大小時,它似乎都認為它是整個文件的大小,而不僅僅是一個塊。例如上傳 15m 文件時,我希望看到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 mainimport (    "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)
查看完整描述

3 回答

?
繁花不似錦

TA貢獻1851條經驗 獲得超4個贊

當您將文件部分傳遞給multi.PutPart方法 (n, strings.NewReader ("")) 時,您的代碼必須更改一些點才能使其正常工作,下面的代碼將起作用。


記住 PutPart 發送分段上傳的一部分,從 r 讀取所有內容,除了最后一個部分,每個部分的大小必須至少為 5MB。 它在 goamz 文檔中有描述。


我已更改為正常工作的要點:


在這里,我使用文件的所有字節創建我們的 headerPart


HeaderPart: = strings.NewReader (string (bytes) )


這里io.ReadFull (HeaderPart, partBuffer)我正在讀取make ([] byte, 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")

}


查看完整回答
反對 回復 2021-12-06
?
Qyouu

TA貢獻1786條經驗 獲得超11個贊

您讀入的數據partBuffer根本沒有使用。您傳遞filemulti.PutPart并讀取全部內容file,求它回到起點為必要吹你做的工作之外的所有。

你的代碼最小的變化將是通過bytes.NewReader(partBuffer)進入PutPart,而不是file。bytes.Reader實現需要的io.ReadSeeker接口PutPart,并將其大小報告為partBuffer.

另一種方法是使用io.SectionReader類型 - 而不是自己將數據讀入緩沖區,您只需SectionReader根據file您想要的大小和偏移量創建一系列s并將它們傳遞給PutPart,它們將傳遞讀取到底層文件閱讀器。這應該也能正常工作,并大大減少您必須編寫(和錯誤檢查)的代碼。它還避免了在 RAM 中不必要地緩沖整個數據塊。


查看完整回答
反對 回復 2021-12-06
?
嚕嚕噠

TA貢獻1784條經驗 獲得超7個贊

這里的問題可能是由于沒有完全讀取文件造成的。Read可能有點微妙:


Read 將最多 len(p) 個字節讀入 p。它返回讀取的字節數 (0 <= n <= len(p)) 和遇到的任何錯誤。即使 Read 返回 n < len(p),它也可能在調用期間使用所有 p 作為暫存空間。如果某些數據可用但 len(p) 字節不可用,則 Read 通常會返回可用的數據,而不是等待更多數據。


所以你可能應該使用ioReadFullor (better) 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上找到更多文檔。


查看完整回答
反對 回復 2021-12-06
  • 3 回答
  • 0 關注
  • 408 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號