finish two features

This commit is contained in:
codeskyblue 2016-07-26 19:30:59 +08:00
parent bbb1b03f7a
commit 8b129b517b
13 changed files with 129 additions and 3 deletions

View file

@ -16,8 +16,8 @@ If using go1.5, ensure you set GO15VENDOREXPERIMENT=1
1. [x] HTTP Basic Auth 1. [x] HTTP Basic Auth
1. [ ] \.htaccess support 1. [ ] \.htaccess support
1. [x] Partial reload pages when directory change 1. [x] Partial reload pages when directory change
1. [ ] When only one dir under dir, path will combine two together 1. [x] When only one dir under dir, path will combine two together
1. [ ] Directory zip download 1. [x] Directory zip download
1. [ ] Apple ipa auto generate .plist file, qrcode can be recognized by iphone (Require https) 1. [ ] Apple ipa auto generate .plist file, qrcode can be recognized by iphone (Require https)
1. [ ] Support modify the index page 1. [ ] Support modify the index page
1. [ ] Download count statistics 1. [ ] Download count statistics

View file

@ -2,6 +2,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"io/ioutil"
"log" "log"
"net/http" "net/http"
"os" "os"
@ -27,6 +28,7 @@ func NewHTTPStaticServer(root string) *HTTPStaticServer {
m: m, m: m,
} }
m.HandleFunc("/-/raw/{path:.*}", s.hFileOrDirectory) m.HandleFunc("/-/raw/{path:.*}", s.hFileOrDirectory)
m.HandleFunc("/-/zip/{path:.*}", s.hZip)
m.HandleFunc("/-/json/{path:.*}", s.hJSONList) m.HandleFunc("/-/json/{path:.*}", s.hJSONList)
m.HandleFunc("/{path:.*}", s.hIndex).Methods("GET") m.HandleFunc("/{path:.*}", s.hIndex).Methods("GET")
return s 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) { func (s *HTTPStaticServer) hFileOrDirectory(w http.ResponseWriter, r *http.Request) {
path := mux.Vars(r)["path"] path := mux.Vars(r)["path"]
log.Println("Path:", s.Root, 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 "/" Path: filepath.Join(path, file.Name()), // lstrip "/"
} }
if file.IsDir() { 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.Type = "dir"
lr.Size = "-" lr.Size = "-"
} else { } else {
@ -94,3 +104,21 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Write(data) 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
}

View file

@ -87,6 +87,12 @@
</td> </td>
<td>{{f.size}}</td> <td>{{f.size}}</td>
<td style="text-align: center"> <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'"> <template v-if="f.type == 'file'">
<a class="btn btn-default btn-xs" href="/-/raw/{{f.path}}?download=true"> <a class="btn btn-default btn-xs" href="/-/raw/{{f.path}}?download=true">
<span class="hidden-xs">Download</span> <span class="hidden-xs">Download</span>

View file

@ -94,7 +94,7 @@ var vm = new Vue({
e.preventDefault() e.preventDefault()
}, },
updateBreadcrumb: function() { updateBreadcrumb: function() {
var pathname = location.pathname || "/"; var pathname = decodeURI(location.pathname || "/");
var parts = pathname.split('/'); var parts = pathname.split('/');
this.breadcrumb = []; this.breadcrumb = [];
if (pathname == "/") { if (pathname == "/") {

0
testdata/deep1/deep2/deep3/.gitkeep vendored Normal file
View file

0
testdata/filetypes/code.go vendored Normal file
View file

0
testdata/filetypes/image.jpeg vendored Normal file
View file

0
testdata/filetypes/image.jpg vendored Normal file
View file

0
testdata/filetypes/image.pdf vendored Normal file
View file

0
testdata/filetypes/image.png vendored Normal file
View file

0
testdata/filetypes/image.tiff vendored Normal file
View file

0
testdata/中文路径/.gitkeep vendored Normal file
View file

92
zip.go Normal file
View 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)
})
}