英文:
Why is my upload progress bar finishing before the transfer completes?
问题
我正在发送一个POST请求到一个API,并使用第三方库(https://github.com/cheggaaa/pb),但是我的上传进度条在文件传输完成之前就已经完成了。
package main
import(
pb "gopkg.in/cheggaaa/pb.v1"
"net/http"
)
func main() {
file, e := os.Open(path)
if e != nil {
log.Fatal()
}
defer file.Close()
bar := pb.New(int(fi.Size()))
bar.Start()
req, err := http.NewRequest("POST", url, body)
resp, err := client.Do(req)
bar.Finish()
return
}
它开始时显示:
12.64 MB / 12.64 MB [======================] 100.00% 12.59 MB/s 0s
完成后显示:
12.64 MB / 12.64 MB [======================] 100.00% 626.67 KB/s 20s
这是因为HTTP请求处理程序正在将文件读入内存并增加进度条吗?我漏掉了什么?
我查看了这篇帖子(https://stackoverflow.com/questions/26050380/go-tracking-post-request-progress?rq=1),但我不明白它与我使用的库有什么不同。我之前尝试过将文件复制到缓冲区并让进度条读取该缓冲区,但一旦请求被发送,它就会出现相同的情况。
英文:
I'm sending a POST request to an API, and using a third-party library (https://github.com/cheggaaa/pb), but my upload progress bar is going to done before the file transfer actually completes.
package main
import(
pb "gopkg.in/cheggaaa/pb.v1"
"net/http"
)
func main() {
file, e := os.Open(path)
if e != nil {
log.Fatal()
}
defer file.Close()
bar := pb.New(int(fi.Size()))
bar.Start()
req, err := http.NewRequest("POST", url, body)
resp, err := client.Do(req)
bar.Finish()
return
}
It starts at
12.64 MB / 12.64 MB [======================] 100.00% 12.59 MB/s 0s
And at completion goes to:
12.64 MB / 12.64 MB [======================] 100.00% 626.67 KB/s 20s
Is this because the HTTP Req handler is reading the file into memory and incrementing the progress bar? What am I missing?
I checked out this post, (https://stackoverflow.com/questions/26050380/go-tracking-post-request-progress?rq=1), but I don't see how that is different from the library I'm using. I've previously tried using io.Copy
to a buffer with the progress bar reader reading from that, but as soon as the Request is sent it does the same thing.
答案1
得分: 2
如我在评论中所写,你的问题没有包含所有必要的信息,但是这里有一个示例应用程序,它将文件作为multipart-form
发布到远程服务器,并显示进度条:
package main
import (
"github.com/cheggaaa/pb"
"os"
"time"
"bytes"
"mime/multipart"
"io"
"io/ioutil"
"net/http"
)
func main() {
body := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(body)
fw, _ := bodyWriter.CreateFormFile("file", "filename.jpg")
fh, _ := os.Open("filename.jpg")
io.Copy(fw, fh)
bodyWriter.Close()
bar := pb.New(body.Len()).SetUnits(pb.U_BYTES).SetRefreshRate(time.Millisecond * 10)
bar.ShowSpeed = true
bar.Start()
reader := bar.NewProxyReader(body)
resp, _ := http.Post("http://domain.com", bodyWriter.FormDataContentType(), reader)
defer resp.Body.Close()
response, _ := ioutil.ReadAll(resp.Body)
print(string(response))
}
希望对你有帮助!
英文:
As I wrote in the comment, your question doesn't contain all required information, but here is the sample app that posts the file as multipart-form
to the remote server with the progress bar:
package main
import (
"github.com/cheggaaa/pb"
"os"
"time"
"bytes"
"mime/multipart"
"io"
"io/ioutil"
"net/http"
)
func main() {
body := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(body)
fw, _ := bodyWriter.CreateFormFile("file", "filename.jpg")
fh, _ := os.Open("filename.jpg")
io.Copy(fw, fh)
bodyWriter.Close()
bar := pb.New(body.Len()).SetUnits(pb.U_BYTES).SetRefreshRate(time.Millisecond * 10)
bar.ShowSpeed = true
bar.Start()
reader := bar.NewProxyReader(body)
resp, _ := http.Post("http://domain.com", bodyWriter.FormDataContentType(), reader)
defer resp.Body.Close()
response, _ := ioutil.ReadAll(resp.Body)
print(string(response))
}
答案2
得分: 0
明白了,原来另一个包与HTTP请求发生了问题。下面的代码完美地工作。
package main
import (
pb "gopkg.in/cheggaaa/pb.v1"
"fmt"
"os"
"log"
"io/ioutil"
"net/http"
)
func main() {
path := "/Users/me/testfile.txt"
file, e := os.Open(path)
if e != nil {
log.Fatal("文件错误")
}
defer file.Close()
fi, e := file.Stat()
if e != nil {
log.Fatal("文件状态错误")
}
bar := pb.New(int(fi.Size()))
bar.Start()
client := &http.Client{}
req, e := http.NewRequest("POST", "http://posttestserver.com/post.php", bar.NewProxyReader(file))
if e != nil {
log.Fatal("请求错误")
}
resp, e := client.Do(req)
if e != nil {
log.Fatal("响应错误")
}
bar.Finish()
respBody, e := ioutil.ReadAll(resp.Body)
fmt.Println(string(respBody))
return
}
感谢 http://posttestserver.com 提供了一个方便进行故障排除的地方!
英文:
Got it, turns out another package was causing issues with the HTTP Request. The code below works perfectly.
package main
import(
pb "gopkg.in/cheggaaa/pb.v1"
"fmt"
"os"
"log"
"io/ioutil"
"net/http"
)
func main() {
path := "/Users/me/testfile.txt"
file, e := os.Open(path)
if e != nil {
log.Fatal("File Error")
}
defer file.Close()
fi, e := file.Stat()
if e != nil {
log.Fatal("File Stat Error")
}
bar := pb.New(int(fi.Size()))
bar.Start()
client := &http.Client{}
req, e := http.NewRequest("POST", "http://posttestserver.com/post.php", bar.NewProxyReader(file))
if e != nil {
log.Fatal("Request Error")
}
resp, e := client.Do(req)
if e != nil {
log.Fatal("Response Error")
}
bar.Finish()
respBody, e := ioutil.ReadAll(resp.Body)
fmt.Println(string(respBody))
return
}
Thanks to http://posttestserver.com for giving me somewhere to easily troubleshoot!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论