mirror of
https://github.com/hamburghammer/gohttpserver.git
synced 2025-03-14 15:25:56 +01:00
finish two features
This commit is contained in:
parent
bbb1b03f7a
commit
8b129b517b
13 changed files with 129 additions and 3 deletions
|
@ -16,8 +16,8 @@ If using go1.5, ensure you set GO15VENDOREXPERIMENT=1
|
|||
1. [x] HTTP Basic Auth
|
||||
1. [ ] \.htaccess support
|
||||
1. [x] Partial reload pages when directory change
|
||||
1. [ ] When only one dir under dir, path will combine two together
|
||||
1. [ ] Directory zip download
|
||||
1. [x] When only one dir under dir, path will combine two together
|
||||
1. [x] Directory zip download
|
||||
1. [ ] Apple ipa auto generate .plist file, qrcode can be recognized by iphone (Require https)
|
||||
1. [ ] Support modify the index page
|
||||
1. [ ] Download count statistics
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -27,6 +28,7 @@ func NewHTTPStaticServer(root string) *HTTPStaticServer {
|
|||
m: m,
|
||||
}
|
||||
m.HandleFunc("/-/raw/{path:.*}", s.hFileOrDirectory)
|
||||
m.HandleFunc("/-/zip/{path:.*}", s.hZip)
|
||||
m.HandleFunc("/-/json/{path:.*}", s.hJSONList)
|
||||
m.HandleFunc("/{path:.*}", s.hIndex).Methods("GET")
|
||||
return s
|
||||
|
@ -47,6 +49,11 @@ func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *HTTPStaticServer) hZip(w http.ResponseWriter, r *http.Request) {
|
||||
path := mux.Vars(r)["path"]
|
||||
CompressToZip(w, path)
|
||||
}
|
||||
|
||||
func (s *HTTPStaticServer) hFileOrDirectory(w http.ResponseWriter, r *http.Request) {
|
||||
path := mux.Vars(r)["path"]
|
||||
log.Println("Path:", s.Root, path)
|
||||
|
@ -81,6 +88,9 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
|
|||
Path: filepath.Join(path, file.Name()), // lstrip "/"
|
||||
}
|
||||
if file.IsDir() {
|
||||
fileName := deepPath(filepath.Join(s.Root, path), file.Name())
|
||||
lr.Name = fileName
|
||||
lr.Path = filepath.Join(path, fileName)
|
||||
lr.Type = "dir"
|
||||
lr.Size = "-"
|
||||
} else {
|
||||
|
@ -94,3 +104,21 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
|
|||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
func deepPath(basedir, name string) string {
|
||||
isDir := true
|
||||
// loop max 5, incase of for loop not finished
|
||||
maxDepth := 5
|
||||
for depth := 0; depth <= maxDepth && isDir; depth += 1 {
|
||||
finfos, err := ioutil.ReadDir(filepath.Join(basedir, name))
|
||||
if err != nil || len(finfos) != 1 {
|
||||
break
|
||||
}
|
||||
if finfos[0].IsDir() {
|
||||
name = filepath.Join(name, finfos[0].Name())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -87,6 +87,12 @@
|
|||
</td>
|
||||
<td>{{f.size}}</td>
|
||||
<td style="text-align: center">
|
||||
<template v-if="f.type == 'dir'">
|
||||
<a class="btn btn-default btn-xs" href="/-/zip/{{f.path}}">
|
||||
Archieve Zip
|
||||
<span class="glyphicon glyphicon-download-alt"></span>
|
||||
</a>
|
||||
</template>
|
||||
<template v-if="f.type == 'file'">
|
||||
<a class="btn btn-default btn-xs" href="/-/raw/{{f.path}}?download=true">
|
||||
<span class="hidden-xs">Download</span>
|
||||
|
|
|
@ -94,7 +94,7 @@ var vm = new Vue({
|
|||
e.preventDefault()
|
||||
},
|
||||
updateBreadcrumb: function() {
|
||||
var pathname = location.pathname || "/";
|
||||
var pathname = decodeURI(location.pathname || "/");
|
||||
var parts = pathname.split('/');
|
||||
this.breadcrumb = [];
|
||||
if (pathname == "/") {
|
||||
|
|
0
testdata/deep1/deep2/deep3/.gitkeep
vendored
Normal file
0
testdata/deep1/deep2/deep3/.gitkeep
vendored
Normal file
0
testdata/filetypes/code.go
vendored
Normal file
0
testdata/filetypes/code.go
vendored
Normal file
0
testdata/filetypes/image.jpeg
vendored
Normal file
0
testdata/filetypes/image.jpeg
vendored
Normal file
0
testdata/filetypes/image.jpg
vendored
Normal file
0
testdata/filetypes/image.jpg
vendored
Normal file
0
testdata/filetypes/image.pdf
vendored
Normal file
0
testdata/filetypes/image.pdf
vendored
Normal file
0
testdata/filetypes/image.png
vendored
Normal file
0
testdata/filetypes/image.png
vendored
Normal file
0
testdata/filetypes/image.tiff
vendored
Normal file
0
testdata/filetypes/image.tiff
vendored
Normal file
0
testdata/中文路径/.gitkeep
vendored
Normal file
0
testdata/中文路径/.gitkeep
vendored
Normal file
92
zip.go
Normal file
92
zip.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Zip struct {
|
||||
*zip.Writer
|
||||
}
|
||||
|
||||
func sanitizedName(filename string) string {
|
||||
if len(filename) > 1 && filename[1] == ':' &&
|
||||
runtime.GOOS == "windows" {
|
||||
filename = filename[2:]
|
||||
}
|
||||
filename = strings.TrimLeft(strings.Replace(filename, `\`, "/", -1), `/`)
|
||||
filename = filepath.ToSlash(filename)
|
||||
filename = filepath.Clean(filename)
|
||||
return filename
|
||||
}
|
||||
|
||||
func statFile(filename string) (info os.FileInfo, reader io.ReadCloser, err error) {
|
||||
info, err = os.Lstat(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// content
|
||||
if info.Mode()&os.ModeSymlink != 0 {
|
||||
var target string
|
||||
target, err = os.Readlink(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
reader = ioutil.NopCloser(bytes.NewBuffer([]byte(target)))
|
||||
} else if !info.IsDir() {
|
||||
reader, err = os.Open(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
reader = ioutil.NopCloser(bytes.NewBuffer(nil))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *Zip) Add(relpath, abspath string) error {
|
||||
info, rdc, err := statFile(abspath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rdc.Close()
|
||||
|
||||
hdr, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.Name = sanitizedName(relpath)
|
||||
if info.IsDir() {
|
||||
hdr.Name += "/"
|
||||
}
|
||||
hdr.Method = zip.Deflate // compress method
|
||||
writer, err := z.CreateHeader(hdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(writer, rdc)
|
||||
return err
|
||||
}
|
||||
|
||||
func CompressToZip(w http.ResponseWriter, rootDir string) {
|
||||
rootDir = filepath.Clean(rootDir)
|
||||
zipFileName := filepath.Base(rootDir) + ".zip"
|
||||
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", `attachment; filename="`+zipFileName+`"`)
|
||||
|
||||
zw := &Zip{Writer: zip.NewWriter(w)}
|
||||
defer zw.Close()
|
||||
|
||||
filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
zipPath := path[len(rootDir):]
|
||||
return zw.Add(zipPath, path)
|
||||
})
|
||||
}
|
Loading…
Add table
Reference in a new issue