File: download-with-progressbar.go

package info (click to toggle)
golang-github-pterm-pterm 0.12.79-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,640 kB
  • sloc: makefile: 4
file content (68 lines) | stat: -rw-r--r-- 1,844 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package putils

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"

	"github.com/pterm/pterm"
)

// progressbarWriter counts the number of bytes written to it and adds those to a progressbar.
type progressbarWriter struct {
	Total uint64
	pb    *pterm.ProgressbarPrinter
}

func (w *progressbarWriter) Write(p []byte) (int, error) {
	n := len(p)
	w.Total += uint64(n)
	w.pb.Add(len(p))
	return n, nil
}

// DownloadFileWithProgressbar downloads a file, by url, and writes it to outputPath.
// The download progress, will be reported via a progressbar.
func DownloadFileWithProgressbar(progressbar *pterm.ProgressbarPrinter, outputPath, url string, mode os.FileMode) error {
	path := filepath.Clean(outputPath)
	out, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("could not create download path: %w", err)
	}

	resp, err := http.Get(url) //nolint:gosec
	if err != nil {
		out.Close()
		return fmt.Errorf("error while downloading file: %w", err)
	}
	defer resp.Body.Close()

	counter := &progressbarWriter{}
	fileSize, err := strconv.Atoi(resp.Header.Get("Content-Length"))
	if err != nil {
		return fmt.Errorf("could not determine file size: %w", err)
	}

	counter.pb, _ = progressbar.WithTotal(fileSize).Start()
	if _, err = io.Copy(out, io.TeeReader(resp.Body, counter)); err != nil {
		out.Close()
		return err
	}

	err = os.Chmod(path, mode)
	if err != nil {
		return fmt.Errorf("could not chmod file: %w", err)
	}

	out.Close()
	return nil
}

// DownloadFileWithDefaultProgressbar downloads a file, by url, and writes it to outputPath.
// The download progress, will be reported via the default progressbar.
func DownloadFileWithDefaultProgressbar(title, outputPath, url string, mode os.FileMode) error {
	return DownloadFileWithProgressbar(pterm.DefaultProgressbar.WithTitle(title), outputPath, url, mode)
}