From 500e0890d86fa5947b225b588e31e21e3daa71e2 Mon Sep 17 00:00:00 2001 From: Sergey Grebenshchikov Date: Wed, 14 Nov 2018 00:57:40 +0100 Subject: [PATCH] Add .zip download --- Makefile | 2 +- README.md | 8 ++++---- server.go | 24 ++++++++++++++++++++++-- zip.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 zip.go diff --git a/Makefile b/Makefile index fe5493a..f696329 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 1.0.0 +VERSION = 1.1.0 APP := http-file-server PACKAGES := $(shell go list -f {{.Dir}} ./...) diff --git a/README.md b/README.md index af57e70..8f4c0b7 100644 --- a/README.md +++ b/README.md @@ -57,14 +57,14 @@ Or [download a binary](https://github.com/sgreben/http-file-server/releases/late ```sh # Linux -curl -L https://github.com/sgreben/http-file-server/releases/download/1.0.0/http-file-server_1.0.0_linux_x86_64.tar.gz | tar xz +curl -L https://github.com/sgreben/http-file-server/releases/download/1.1.0/http-file-server_1.1.0_linux_x86_64.tar.gz | tar xz # OS X -curl -L https://github.com/sgreben/http-file-server/releases/download/1.0.0/http-file-server_1.0.0_osx_x86_64.tar.gz | tar xz +curl -L https://github.com/sgreben/http-file-server/releases/download/1.1.0/http-file-server_1.1.0_osx_x86_64.tar.gz | tar xz # Windows -curl -LO https://github.com/sgreben/http-file-server/releases/download/1.0.0/http-file-server_1.0.0_windows_x86_64.zip -unzip versions_1.0.0_windows_x86_64.zip +curl -LO https://github.com/sgreben/http-file-server/releases/download/1.1.0/http-file-server_1.1.0_windows_x86_64.zip +unzip versions_1.1.0_windows_x86_64.zip ``` ## Use it diff --git a/server.go b/server.go index ed49d54..7cc6fa6 100644 --- a/server.go +++ b/server.go @@ -15,6 +15,10 @@ const ( tarGzKey = "tar.gz" tarGzValue = "true" tarGzContentType = "application/x-tar+gzip" + + zipKey = "zip" + zipValue = "true" + zipContentType = "application/zip" ) type fileHandler struct { @@ -35,13 +39,20 @@ func (f *fileHandler) serveStatus(w http.ResponseWriter, r *http.Request, status w.Write([]byte(http.StatusText(status))) } -func (f *fileHandler) serveZip(w http.ResponseWriter, r *http.Request, path string) { +func (f *fileHandler) serveTarGz(w http.ResponseWriter, r *http.Request, path string) { w.Header().Set("Content-Type", tarGzContentType) name := filepath.Base(path) + ".tar.gz" w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename=%q`, name)) tarGz(w, path) } +func (f *fileHandler) serveZip(w http.ResponseWriter, r *http.Request, path string) { + w.Header().Set("Content-Type", zipContentType) + name := filepath.Base(path) + ".zip" + w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename=%q`, name)) + zip(w, path) +} + func (f *fileHandler) serveDir(w http.ResponseWriter, r *http.Request, dirPath string) { d, err := os.Open(dirPath) if err != nil { @@ -77,6 +88,13 @@ func (f *fileHandler) serveDir(w http.ResponseWriter, r *http.Request, dirPath s fmt.Fprintf(w, "

\n") fmt.Fprintf(w, "Entire directory as .tar.gz\n", url.String()) fmt.Fprintf(w, "

\n") + url.RawQuery = "" + q = url.Query() + q.Set(zipKey, zipValue) + url.RawQuery = q.Encode() + fmt.Fprintf(w, "

\n") + fmt.Fprintf(w, "Entire directory as .zip\n", url.String()) + fmt.Fprintf(w, "

\n") } } @@ -98,8 +116,10 @@ func (f *fileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { f.serveStatus(w, r, http.StatusForbidden) case err != nil: f.serveStatus(w, r, http.StatusInternalServerError) - case r.URL.Query().Get(tarGzKey) != "": + case r.URL.Query().Get(zipKey) != "": f.serveZip(w, r, path) + case r.URL.Query().Get(tarGzKey) != "": + f.serveTarGz(w, r, path) case info.IsDir(): f.serveDir(w, r, path) default: diff --git a/zip.go b/zip.go new file mode 100644 index 0000000..8831ad0 --- /dev/null +++ b/zip.go @@ -0,0 +1,44 @@ +package main + +import ( + zipper "archive/zip" + "io" + "log" + "os" + "path/filepath" +) + +func zip(w io.Writer, path string) error { + basePath := path + addFile := func(w *zipper.Writer, path string, stat os.FileInfo) error { + if stat.IsDir() { + return nil + } + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + path, err = filepath.Rel(basePath, path) + zw, err := w.Create(path) + if err != nil { + return err + } + if _, err := io.Copy(zw, file); err != nil { + return err + } + return w.Flush() + } + wZip := zipper.NewWriter(w) + defer func() { + if err := wZip.Close(); err != nil { + log.Println(err) + } + }() + return filepath.Walk(path, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + return addFile(wZip, path, info) + }) +}