go 下载文件增加进度条
方式1: 在writer层进行增加功能
var (
GOOGLE_APPLICATION_CREDENTIALS = "/gcs.json"
)
type Writer struct {
total int64
current int64
}
//没用到
func (w *Writer) getFileSize(bucket string, object string) {
ctx := context.Background()
client, err := storage.NewClient(ctx)
if err != nil {
fmt.Errorf("storage.NewClient: %v", err)
}
defer client.Close()
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
o := client.Bucket(bucket).Object(object)
attrs, _ := o.Attrs(ctx)
w.total = attrs.Size
}
func (w *Writer) Write(b []byte) (n int, err error) {
length := len(b)
w.current += int64(length)
w.PrintProgress()
return length, nil
}
func (w *Writer) PrintProgress() {
// Return again and print current status of download
// We use the humanize package to print the bytes in a meaningful way (e.g. 10 MB)
fmt.Printf("\rDownloading... %0.2f%% complete", float64(w.current*100)/float64(w.total))
}
func downloadFileWithProgress(w io.Writer, bucket, object string, destFileName string) error {
ctx := context.Background()
client, err := storage.NewClient(ctx)
if err != nil {
return fmt.Errorf("storage.NewClient: %v", err)
}
defer client.Close()
ctx, cancel := context.WithTimeout(ctx, time.Second*6000)
defer cancel()
f, err := os.Create(destFileName)
if err != nil {
return fmt.Errorf("os.Create: %v", err)
}
rc, err := client.Bucket(bucket).Object(object).NewReader(ctx)
if err != nil {
return fmt.Errorf("Object(%q).NewReader: %v", object, err)
}
defer rc.Close()
writer := &Writer{total: rc.Attrs.Size}
//TeeReader()函数用于返回“Reader”,该“Reader”从声明的“r”读取,然后将其写入声明的“w”。
//将通过声明的“r”执行的所有读取与对声明的“w”的等效写入进行比较。此方法不需要任何内部缓冲
//并且读取完成后即可完成写入
if _, err := io.Copy(f, io.TeeReader(rc, writer)); err != nil {
return fmt.Errorf("io.Copy: %v", err)
}
if err = f.Close(); err != nil {
return fmt.Errorf("f.Close: %v", err)
}
fmt.Fprintf(w, "Blob %v downloaded to local file %v\n", object, destFileName)
return nil
}
// 环境变量设置
func init() {
pwd, err := os.Getwd()
if err != nil {
panic(err)
}
os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", {env})
}
func main() {
err := downloadFileWithProgress(os.Stdout, "{gcs-bucketname}", "test01.csv", "./test01.csv")
if err != nil {
panic(err)
}
}
效果:
方式二:在reader侧增加功能
todo