Arrays 跟踪和显示下载文件摘要(百分比)-Go lang
我正在做一个通过传递的url参数下载文件的过程。下载正在正确完成,但我不能做的是打印下载完成百分比的摘要。(每秒钟) 我做了一个模拟的总结,但它没有下载任何东西,它只是为了显示我想要它 我试图将io.copy放在我的源代码中,以便在复制过程中对其进行更改和打印,但失败了 有人能帮我吗? 谢谢Arrays 跟踪和显示下载文件摘要(百分比)-Go lang,arrays,io,go,byte,Arrays,Io,Go,Byte,我正在做一个通过传递的url参数下载文件的过程。下载正在正确完成,但我不能做的是打印下载完成百分比的摘要。(每秒钟) 我做了一个模拟的总结,但它没有下载任何东西,它只是为了显示我想要它 我试图将io.copy放在我的源代码中,以便在复制过程中对其进行更改和打印,但失败了 有人能帮我吗? 谢谢 主程序包 进口( “fmt” “io” “net/http” “操作系统” “字符串” //“时间” ) func downloadFromUrl(url字符串){ 标记:=strings.Split(ur
主程序包
进口(
“fmt”
“io”
“net/http”
“操作系统”
“字符串”
//“时间”
)
func downloadFromUrl(url字符串){
标记:=strings.Split(url,“/”)
文件名:=令牌[len(令牌)-1]
Println(“下载”,url,“至”,文件名)
//创建文件
输出,错误:=os.Create(文件名)
如果错误!=零{
Println(“创建时出错”,文件名“-”,错误)
返回
}
fmt.Println(“创建”,文件名)
延迟输出。关闭()
//获取url
响应,错误:=http.Get(url)
如果错误!=零{
fmt.Println(“下载时出错”,url,“-”,err)
返回
}
延迟响应。Body.Close()
//拷贝和字节
n、 err:=io.Copy(输出,响应,正文)
如果错误!=零{
fmt.Println(“下载时出错”,url,“-”,err)
返回
}
//跟踪进度
对于i:=1;float64(i)
我用io.Reader
包装器在我的
// PassThru wraps an existing io.Reader.
//
// It simply forwards the Read() call, while displaying
// the results from individual calls to it.
type PassThru struct {
io.Reader
total int64 // Total # of bytes transferred
length int64 // Expected length
progress float64
}
在该包装器上定义一个Read()
方法(使其成为io.Reader
)
您可以使用该io.Reader
读取(http请求的结果):
调用ReadAll()
将触发实际下载,而PassThru.Read()
将根据预期长度(response.ContentLength
)打印下载的百分比
灵感:
- 这是Copy()函数的一个例子
- “”
err==nil
那么n==0
。那不一定是真的Read最多可将len(p)字节读入p。它返回读取的字节数(0@peterSO我不知道:在上面的代码中,如果err==nil
,你在哪里看到func(pt*PassThru)读取(p[]byte)(int,error)
你有if err==nil{pt.total+=int64(n)}
。如果err!=nil
,您不应该将n
添加到pt.total
中,您应该。CORRECTION s/err==nil/err!=nil/:您似乎假设如果err!=nil
那么n==0
。这不一定是真的。包io类型读取器:Read最多读取到p中的len(p)字节。它返回读取的字节数(0@peterSO我最终猜到了这一点(这就是我最初没有关注您的原因)。相关文档是:“调用方在考虑错误err
之前,应该始终处理返回的n>0
字节。这样做可以正确地处理读取某些字节后发生的I/O错误以及两种允许的EOF行为。”
// PassThru wraps an existing io.Reader.
//
// It simply forwards the Read() call, while displaying
// the results from individual calls to it.
type PassThru struct {
io.Reader
total int64 // Total # of bytes transferred
length int64 // Expected length
progress float64
}
// Read 'overrides' the underlying io.Reader's Read method.
// This is the one that will be called by io.Copy(). We simply
// use it to keep track of byte counts and then forward the call.
func (pt *PassThru) Read(p []byte) (int, error) {
n, err := pt.Reader.Read(p)
if n > 0 {
pt.total += int64(n)
percentage := float64(pt.total) / float64(pt.length) * float64(100)
i := int(percentage / float64(10))
is := fmt.Sprintf("%v", i)
if percentage-pt.progress > 2 {
fmt.Fprintf(os.Stderr, is)
pt.progress = percentage
}
}
return n, err
}
client := &http.Client{
CheckRedirect: redirectPolicyFunc,
}
response, err := client.Get("http://example.com/something/large.zip")
defer response.Body.Close()
readerpt := &PassThru{Reader: response.Body, length: response.ContentLength}
body, err := ioutil.ReadAll(readerpt)