Golang 实现带进度条的文件下载功能
发表时间: 2024-05-21 11:16
普通文件下载
package mainimport ("io""net/http""os")func main() { // 下载地址: fileUrl := "http://xxxxxx.com/files/" if err := DownloadFile("保存文件名.png", fileUrl); err != nil { panic(err) } } // download file会将url下载到本地文件,它会在下载时写入,而不是将整个文件加载到内存中。 func DownloadFile(filepath string, url string) error { // Get the data resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() // Create the file out, err := os.Create(filepath) if err != nil { return err } defer out.Close() // Write the body to file _, err = io.Copy(out, resp.Body) return err}
带进度条的大文件下载
package mainimport ( "fmt" "io" "net/http" "os" "strings" "github.com/dustin/go-humanize")type WriteCounter struct { Total uint64}func (wc *WriteCounter) Write(p []byte) (int, error) { n := len(p) wc.Total += uint64(n) wc.PrintProgress() return n, nil}func (wc WriteCounter) PrintProgress() { fmt.Printf("\r%s", strings.Repeat(" ", 35)) fmt.Printf("\rDownloading... %s complete", humanize.Bytes(wc.Total))}func main() { fmt.Println("Download Started") // 下载地址: fileUrl := "http://xxxxxx.com/files/文件名称"" err := DownloadFile("保存文件名.png", fileUrl) if err != nil { panic(err) } fmt.Println("Download Finished")}func DownloadFile(filepath string, url string) error { out, err := os.Create(filepath + ".tmp") if err != nil { return err } resp, err := http.Get(url) if err != nil { out.Close() return err } defer resp.Body.Close() counter := &WriteCounter{} /* io.TeeReader则可以传递计数器来跟踪进度 io.TeeReader返回一个将其从r读取的数据写入w的Reader接口。所有通过该接口对r的读取都会执行对应的对w的写入。没有内部的缓冲; 写入必须在读取完成前完成。写入时遇到的任何错误都会作为读取错误返回。 */ if _, err = io.Copy(out, io.TeeReader(resp.Body, counter)); err != nil { out.Close() return err } fmt.Print("\n") out.Close() if err = os.Rename(filepath+".tmp", filepath); err != nil { return err } return nil}