diff --git a/http/download.go b/http/download.go index 5ec116a2..bfc8b6e4 100644 --- a/http/download.go +++ b/http/download.go @@ -1,8 +1,6 @@ package http import ( - "io" - "io/ioutil" "net/http" "net/url" "os" @@ -45,72 +43,41 @@ func downloadHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int files = append(files, c.File.Path) } - // If the format is true, just set it to "zip". - if query == "true" || query == "" { - query = "zip" - } - var ( extension string - temp string - err error - tempfile string + ar archiver.Archiver ) - // Create a temporary directory. - temp, err = ioutil.TempDir("", "") - if err != nil { - return http.StatusInternalServerError, err - } - defer os.RemoveAll(temp) - - tempfile = filepath.Join(temp, "temp") - switch query { - case "zip": - extension, err = ".zip", archiver.Zip.Make(tempfile, files) + // If the format is true, just set it to "zip". + case "zip", "true", "": + extension, ar = ".zip", archiver.Zip case "tar": - extension, err = ".tar", archiver.Tar.Make(tempfile, files) + extension, ar = ".tar", archiver.Tar case "targz": - extension, err = ".tar.gz", archiver.TarGz.Make(tempfile, files) + extension, ar = ".tar.gz", archiver.TarGz case "tarbz2": - extension, err = ".tar.bz2", archiver.TarBz2.Make(tempfile, files) + extension, ar = ".tar.bz2", archiver.TarBz2 case "tarxz": - extension, err = ".tar.xz", archiver.TarXZ.Make(tempfile, files) + extension, ar = ".tar.xz", archiver.TarXZ default: return http.StatusNotImplemented, nil } - if err != nil { - return http.StatusInternalServerError, err - } - // Defines the file name. name := c.File.Name if name == "." || name == "" { - name = "download" + name = "archive" } name += extension - // Opens the file so it can be downloaded. - file, err := os.Open(temp + "/temp") - if err != nil { - return http.StatusInternalServerError, err - } - defer file.Close() + w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.QueryEscape(name)) + err := ar.Write(w, files) - w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"") - _, err = io.Copy(w, file) return 0, err } func downloadFileHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) { - if r.URL.Query().Get("inline") == "true" { - w.Header().Set("Content-Disposition", "inline") - } else { - w.Header().Set("Content-Disposition", `attachment; filename="`+c.File.Name+`"`) - } - file, err := os.Open(c.File.Path) defer file.Close() @@ -118,10 +85,19 @@ func downloadFileHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) return http.StatusInternalServerError, err } - _, err = io.Copy(w, file) + stat, err := file.Stat() if err != nil { return http.StatusInternalServerError, err } + if r.URL.Query().Get("inline") == "true" { + w.Header().Set("Content-Disposition", "inline") + } else { + // As per RFC6266 section 4.3 + w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.QueryEscape(c.File.Name)) + } + + http.ServeContent(w, r, stat.Name(), stat.ModTime(), file) + return 0, nil }