为什么我的上传进度条在传输完成之前就已经完成了?

huangapple go评论99阅读模式
英文:

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!

huangapple
  • 本文由 发表于 2017年1月24日 14:11:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/41821193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定