package downloader import ( "errors" "io" "net/http" "os" "strings" req "github.com/levigross/grequests" "github.com/schollz/progressbar/v3" ) var ( ErrAccessDenied = errors.New("restricted access (credentials required)") ErrInvalidURL = errors.New("invalid url") ErrUnknownAuthority = errors.New("certificate from unknown authority") ) type Context struct { Filename string Link string } func NewContext(filename, link string) *Context { return &Context{ Filename: filename, Link: link, } } func (c *Context) Download() error { resp, err := req.Head(c.Link, nil) if err != nil { if strings.Contains(err.Error(), "no such host") { return ErrInvalidURL } if strings.Contains(err.Error(), "certificate signed by unknown authority") { return ErrUnknownAuthority } return err } defer resp.Close() if resp.StatusCode == http.StatusNotFound { return ErrInvalidURL } if resp.StatusCode == http.StatusUnauthorized { return ErrAccessDenied } if resp.StatusCode != http.StatusOK { return errors.New(resp.RawResponse.Status) } resp.Close() resp, err = req.Get(c.Link, nil) if err != nil { return err } var filesize int64 if resp.RawResponse.ContentLength > -1 { filesize = resp.RawResponse.ContentLength } destFile, err := os.OpenFile(c.Filename, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer destFile.Close() bar := progressbar.DefaultBytes( filesize, "downloading", ) _, err = io.Copy(io.MultiWriter(destFile, bar), resp.RawResponse.Body) if err != nil { return err } return nil } func (c *Context) FileExists() bool { _, err := os.Stat(c.Filename) return !errors.Is(err, os.ErrNotExist) }