2014-09-26 139 views
2

我在Go中爲Linux編碼ShareX克隆,通過http POST請求將文件和圖像上傳到文件共享服務。前往:跟蹤POST請求進度

我目前使用http.Client和Do()來發送我的請求,但是我希望能夠跟蹤大文件的上傳進度,上傳最多需要一分鐘時間。 我現在唯一能想到的方法是手動打開端口80上的TCP連接到網站,並將HTTP請求分塊寫入,但我不知道它是否可以在https網站上運行,而且我不確定如果這是最好的辦法。

有沒有其他辦法可以達到這個目的?

回答

4

您可以創建自己的io.Reader來包裝實際的閱讀器,然後可以輸出每次調用Read時的進度。

線沿線的東西:

type ProgressReader struct { 
    io.Reader 
    Reporter func(r int64) 
} 

func (pr *ProgressReader) Read(p []byte) (n int, err error) { 
    n, err = pr.Reader.Read(p) 
    pr.Reporter(int64(n)) 
    return 
} 

func main() { 
    file, _ := os.Open("/tmp/blah.go") 
    total := int64(0) 
    pr := &ProgressReader{file, func(r int64) { 
     total += r 
     if r > 0 { 
      fmt.Println("progress", r) 
     } else { 
      fmt.Println("done", r) 
     } 
    }} 
    io.Copy(ioutil.Discard, pr) 
} 
+0

真的很聰明..你們倆! +1! – 2014-09-26 01:16:35

+0

我在我的papertrails項目中有一個[工作示例](https://github.com/dustin/papertrails/blob/master/progress.go),用於跟蹤上傳到S3。 – Dustin 2014-09-26 04:02:21

+0

我從來沒有想過這個!謝謝你們的答案。 – 2014-09-26 12:08:05

2

總結與一些報道正在進行的請求體傳遞的讀者。例如,

type progressReporter struct { 
    r io.Reader 
    max int 
    sent int 
} 

func (pr *progressReader) Read(p []byte) (int, error) { 
    n, err := pr.r.Read(p) 
    pr.sent += n 
    if err == io.EOF { 
     pr.atEOF = true 
    } 
    pr.report() 
    return n, err 
} 

func (pr *progressReporter) report() { 
    fmt.Printf("sent %d of %d bytes\n", pr.sent, pr.max) 
    if pr.atEOF { 
    fmt.Println("DONE") 
    } 
} 

如果之前你叫

client.Post(u, contentType, r) 

然後更改代碼以

client.Post(u, contentType, &progressReader{r:r, max:max}) 

其中max就是你希望要發送的字節數。修改progressReporter.report()方法並將字段添加到progressReporter以滿足您的特定需求。

+0

我從來沒有想過!謝謝你們的答案。 – 2014-09-26 12:09:17