我在Go中为Linux编写了一个ShareX克隆,它通过http POST请求将文件和图像上传到文件共享服务。
我目前正在使用http.Client和Do()发送我的请求,但我希望能够跟踪上传时间长达一分钟的较大文件的上传进度。 我现在能想到的唯一方法是手动打开端口80上的TCP连接到网站并以块的形式写入HTTP请求,但我不知道它是否适用于https网站,我不确定是否这是最好的方式。
还有其他方法可以达到这个目的吗?
答案 0 :(得分:9)
您可以创建自己的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)
}
答案 1 :(得分:4)
将作为请求正文传递的读者包装起来,报告进度。例如,
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添加字段以满足您的特定需求。