http: download: improvement for range support and I/O (#330)

* http: download: adopt http.ServeContent

* http: download: deprecate unnecessary temp dir

* http: download: adopt http.ServeContent in inline mode
pull/333/head
Equim 2018-01-14 16:41:01 +08:00 committed by Henrique Dias
parent 94648c92a2
commit 30efa23a85
1 changed files with 21 additions and 45 deletions

View File

@ -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
}