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  }