Skip to content

Commit 2f1b558

Browse files
committed
add file search support
1 parent d7e808c commit 2f1b558

File tree

5 files changed

+79
-43
lines changed

5 files changed

+79
-43
lines changed

.fsw.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ triggers:
66
- '**/*.tmpl.html'
77
env:
88
DEBUG: "1"
9-
cmd: (killall gohttpserver; true) && go build && ./gohttpserver --upload&
9+
cmd: go build && ./gohttpserver --upload --root testdata
1010
shell: true
1111
delay: 100ms
1212
signal: KILL

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Upload size now limited to 1G
3535
1. [ ] Offline download
3636
1. [ ] Code file preview
3737
1. [ ] Edit file support
38-
1. [ ] Global file search
38+
1. [x] Global file search
3939
1. [x] Hidden work `download` and `qrcode` in small screen
4040
1. [x] Theme select support
4141
1. [x] OK to working behide Nginx

httpstaticserver.go

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ func (s *HTTPStaticServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5757
s.m.ServeHTTP(w, r)
5858
}
5959

60+
func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
61+
path := mux.Vars(r)["path"]
62+
relPath := filepath.Join(s.Root, path)
63+
64+
finfo, err := os.Stat(relPath)
65+
if err == nil && finfo.IsDir() {
66+
tmpl.ExecuteTemplate(w, "index", s)
67+
} else {
68+
http.ServeFile(w, r, relPath)
69+
}
70+
}
71+
6072
func (s *HTTPStaticServer) hStatus(w http.ResponseWriter, r *http.Request) {
6173
data, _ := json.MarshalIndent(s, "", " ")
6274
w.Header().Set("Content-Type", "application/json")
@@ -99,18 +111,6 @@ func (s *HTTPStaticServer) hUpload(w http.ResponseWriter, req *http.Request) {
99111
w.Write([]byte("Upload success"))
100112
}
101113

102-
func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
103-
path := mux.Vars(r)["path"]
104-
relPath := filepath.Join(s.Root, path)
105-
finfo, err := os.Stat(relPath)
106-
if err == nil && finfo.IsDir() {
107-
tmpl.ExecuteTemplate(w, "index", s)
108-
// tmpl.Execute(w, s)
109-
} else {
110-
http.ServeFile(w, r, relPath)
111-
}
112-
}
113-
114114
func (s *HTTPStaticServer) hZip(w http.ResponseWriter, r *http.Request) {
115115
path := mux.Vars(r)["path"]
116116
CompressToZip(w, filepath.Join(s.Root, path))
@@ -192,7 +192,6 @@ func (s *HTTPStaticServer) hIpaLink(w http.ResponseWriter, r *http.Request) {
192192

193193
func (s *HTTPStaticServer) hFileOrDirectory(w http.ResponseWriter, r *http.Request) {
194194
path := mux.Vars(r)["path"]
195-
log.Println("Path:", s.Root, path)
196195
http.ServeFile(w, r, filepath.Join(s.Root, path))
197196
}
198197

@@ -204,34 +203,64 @@ type ListResponse struct {
204203
}
205204

206205
func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
207-
path := mux.Vars(r)["path"]
208-
lrs := make([]ListResponse, 0)
209-
fd, err := os.Open(filepath.Join(s.Root, path))
210-
if err != nil {
211-
http.Error(w, err.Error(), 500)
212-
return
213-
}
214-
defer fd.Close()
206+
requestPath := mux.Vars(r)["path"]
207+
localPath := filepath.Join(s.Root, requestPath)
208+
search := r.FormValue("search")
215209

216-
files, err := fd.Readdir(-1)
217-
if err != nil {
218-
http.Error(w, err.Error(), 500)
219-
return
210+
// path string -> info os.FileInfo
211+
fileInfoMap := make(map[string]os.FileInfo, 0)
212+
213+
if search != "" {
214+
err := filepath.Walk(localPath, func(path string, info os.FileInfo, err error) error {
215+
if info.IsDir() {
216+
return nil
217+
}
218+
if strings.Contains(strings.ToLower(path), strings.ToLower(search)) {
219+
relPath, _ := filepath.Rel(localPath, path)
220+
fileInfoMap[relPath] = info
221+
}
222+
return nil
223+
})
224+
if err != nil {
225+
http.Error(w, err.Error(), 500)
226+
return
227+
}
228+
} else {
229+
fd, err := os.Open(localPath)
230+
if err != nil {
231+
http.Error(w, err.Error(), 500)
232+
return
233+
}
234+
defer fd.Close()
235+
236+
infos, err := fd.Readdir(-1)
237+
if err != nil {
238+
http.Error(w, err.Error(), 500)
239+
return
240+
}
241+
for _, info := range infos {
242+
fileInfoMap[filepath.Join(requestPath, info.Name())] = info
243+
}
220244
}
221-
for _, file := range files {
245+
246+
lrs := make([]ListResponse, 0)
247+
for path, info := range fileInfoMap {
222248
lr := ListResponse{
223-
Name: file.Name(),
224-
Path: filepath.Join(path, file.Name()), // lstrip "/"
249+
Name: info.Name(),
250+
Path: path, // filepath.Join(path, file.Name()), // lstrip "/"
251+
}
252+
if search != "" {
253+
lr.Name = path
225254
}
226-
if file.IsDir() {
227-
fileName := deepPath(filepath.Join(s.Root, path), file.Name())
228-
lr.Name = fileName
229-
lr.Path = filepath.Join(path, fileName)
255+
if info.IsDir() {
256+
name := deepPath(localPath, info.Name())
257+
lr.Name = name
258+
lr.Path = filepath.Join(filepath.Dir(path), name)
230259
lr.Type = "dir"
231260
lr.Size = "-"
232261
} else {
233262
lr.Type = "file"
234-
lr.Size = formatSize(file)
263+
lr.Size = formatSize(info)
235264
}
236265
lrs = append(lrs, lr)
237266
}

res/index.tmpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
</ul>
3434
<form class="navbar-form navbar-right">
3535
<div class="input-group">
36-
<input type="text" name="search" class="form-control" placeholder="Not finished.">
36+
<input type="text" name="search" class="form-control" placeholder="{{search}}" autofocus required>
3737
<span class="input-group-btn">
3838
<button class="btn btn-default" type="button">
3939
<span class="glyphicon glyphicon-search"></span>

res/js/index.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ function pathJoin(parts, sep) {
1212
return parts.join(separator).replace(replace, separator);
1313
}
1414

15+
function getQueryString(name) {
16+
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
17+
var r = decodeURI(window.location.search).substr(1).match(reg);
18+
if (r != null) return r[2];
19+
return null;
20+
}
21+
1522
var vm = new Vue({
1623
el: "#app",
1724
data: {
@@ -20,6 +27,7 @@ var vm = new Vue({
2027
showHidden: false,
2128
previewFile: null,
2229
version: "loading",
30+
search: getQueryString("search") || "Search text",
2331
files: [{
2432
name: "loading ...",
2533
path: "",
@@ -178,11 +186,13 @@ window.onpopstate = function(event) {
178186

179187
function loadDirectory(reqPath) {
180188
window.history.pushState({}, "", reqPath);
181-
loadFileList()
189+
loadFileList(reqPath)
182190
}
183191

184-
function loadFileList() {
185-
$.getJSON("/-/json" + location.pathname, function(res) {
192+
function loadFileList(pathname) {
193+
var pathname = pathname || location.pathname;
194+
// console.log("load filelist:", pathname)
195+
$.getJSON("/-/json" + pathname, function(res) {
186196
// console.log(res)
187197
res.sort(function(a, b) {
188198
var obj2n = function(v) {
@@ -193,13 +203,10 @@ function loadFileList() {
193203
vm.files = res;
194204
})
195205
vm.updateBreadcrumb();
196-
// if (Dropzone.options.myDropzone) {
197-
// Dropzone.options.myDropzone.url = location.pathname;
198-
// }
199206
}
200207

201208
// For page first loading
202-
loadFileList()
209+
loadFileList(location.pathname + location.search)
203210

204211
// update version
205212
$.getJSON("/-/sysinfo", function(res) {

0 commit comments

Comments
 (0)