rangeというのをheaderにセットすると、途中から途中までをダウンロードできるのか。これで分割ダウンロードとかリジュームとかできるらしい。pgetみながら自分でも一応簡単なダウンロード+Progress barをつくってみた。
main.go
package main import ( "fmt" "net/http" "log" "os" "io" ) var target_url = "https://www.imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-7.0.6-0.x86_64.rpm" var out_dir = "." type Target struct { url string dir_path string file_name string file_size int64 } func main() { fmt.Println("test file download") target := Target{ url: target_url, dir_path: out_dir, } check(&target) download(&target) } func check(t *Target) { fmt.Println("checking url...") res, err := http.Head(t.url) chkErr(err) if res.Header.Get("Accept-Ranges") != "bytes" { log.Fatal("not supported range access.") } if res.ContentLength <= 0 { log.Fatal("invalid content length.") } t.file_size = int64(res.ContentLength) t.file_name = GetFileName(t.url) fmt.Println("check ok.") } func download(t *Target){ fmt.Println("downloading...") req, err := http.NewRequest("GET", t.url, nil) chkErr(err) req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", 0, t.file_size)) res, err := http.DefaultClient.Do(req) chkErr(err) defer res.Body.Close() out_path := GetFilePath(t.dir_path, t.file_name) out, err := os.Create(out_path) chkErr(err) defer out.Close() ch := make(chan int) go ProgressBar(t, &out_path, ch) io.Copy(out, res.Body) <- ch } func chkErr(err error){ if err != nil { log.Fatal(err) } }
util.go
package main import ( "gopkg.in/cheggaaa/pb.v2" "time" "net/url" "path/filepath" "os" ) func GetFileName(u string) string { result, err := url.Parse(u) chkErr(err) return filepath.Base(result.Path) } func GetFilePath(d, f string) string { return filepath.Join(d, f) } func ProgressBar(t *Target, file_path *string, ch chan int){ file_size := t.file_size now_size := int64(0) bar := pb.Start64(file_size) for { fi, err := os.Stat(*file_path) chkErr(err) now_size = fi.Size() if now_size < file_size { bar.SetCurrent(now_size) } else { bar.SetCurrent(file_size) bar.Finish() ch <- 1 break } time.Sleep(100 * time.Millisecond) } }