github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/fileutils/file_download.go (about) 1 package fileutils 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "os" 8 "path/filepath" 9 "strings" 10 ) 11 12 type Downloader interface { 13 DownloadFile(string) (int64, string, error) 14 RemoveFile() error 15 } 16 17 type downloader struct { 18 saveDir string 19 filename string 20 } 21 22 func NewDownloader(saveDir string) Downloader { 23 return &downloader{ 24 saveDir: saveDir, 25 } 26 } 27 28 //this func returns byte written, filename and error 29 func (d *downloader) DownloadFile(url string) (int64, string, error) { 30 c := http.Client{ 31 CheckRedirect: func(r *http.Request, via []*http.Request) error { 32 r.URL.Opaque = r.URL.Path 33 34 //some redirect return '/' as url 35 if strings.Trim(r.URL.Opaque, "/") != "" { 36 url = r.URL.Opaque 37 } 38 39 return nil 40 }, 41 } 42 43 r, err := c.Get(url) 44 45 if err != nil { 46 return 0, "", err 47 } 48 defer r.Body.Close() 49 50 if r.StatusCode == 200 { 51 d.filename = get_filename_from_header(r.Header.Get("Content-Disposition")) 52 53 if d.filename == "" { 54 d.filename = get_filename_from_url(url) 55 } 56 57 f, err := os.Create(filepath.Join(d.saveDir, d.filename)) 58 if err != nil { 59 return 0, "", err 60 } 61 defer f.Close() 62 63 size, err := io.Copy(f, r.Body) 64 if err != nil { 65 return 0, "", err 66 } 67 68 return size, d.filename, nil 69 70 } else { 71 return 0, "", fmt.Errorf("Error downloading file from %s", url) 72 } 73 } 74 75 func (d *downloader) RemoveFile() error { 76 return os.Remove(filepath.Join(d.saveDir, d.filename)) 77 } 78 79 func get_filename_from_header(h string) string { 80 if h == "" { 81 return "" 82 } 83 84 contents := strings.Split(h, ";") 85 for _, content := range contents { 86 if strings.Contains(content, "filename=") { 87 name := strings.TrimLeft(content, "filename=") 88 return strings.Trim(name, `"`) 89 } 90 } 91 92 return "" 93 } 94 95 func get_filename_from_url(url string) string { 96 tmp := strings.Split(url, "/") 97 token := tmp[len(tmp)-1] 98 99 if i := strings.LastIndex(token, "?"); i != -1 { 100 token = token[i+1:] 101 } 102 103 if i := strings.LastIndex(token, "&"); i != -1 { 104 token = token[i+1:] 105 } 106 107 if i := strings.LastIndex(token, "="); i != -1 { 108 return token[i+1:] 109 } 110 111 return token 112 }