Skip to content

Commit faae3b1

Browse files
committed
feat(serverHandler): support upload files of directories
1 parent fed3a35 commit faae3b1

File tree

3 files changed

+110
-17
lines changed

3 files changed

+110
-17
lines changed

src/serverHandler/mutate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func (h *handler) mutate(w http.ResponseWriter, r *http.Request, data *responseD
1111
switch {
1212
case data.IsUpload:
1313
if data.CanUpload && r.Method == http.MethodPost {
14-
success = h.saveUploadFiles(h.root+data.handlerReqPath, data.CanDelete, data.AliasSubItems, r)
14+
success = h.saveUploadFiles(h.root+data.handlerReqPath, data.CanMkdir, data.CanDelete, data.AliasSubItems, r)
1515
}
1616
case data.IsMkdir:
1717
if data.CanMkdir && !h.errHandler.LogError(r.ParseForm()) {

src/serverHandler/upload.go

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import (
1111
"strings"
1212
)
1313

14+
const file = "file"
15+
const dirFile = "dirfile"
16+
const innerDirFile = "innerdirfile"
17+
1418
func getAvailableFilename(fsPrefix, filename string, mustAppendSuffix bool) string {
1519
if len(fsPrefix) == 0 {
1620
fsPrefix = "/"
@@ -36,7 +40,7 @@ func getAvailableFilename(fsPrefix, filename string, mustAppendSuffix bool) stri
3640
return ""
3741
}
3842

39-
func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSubItems []os.FileInfo, r *http.Request) bool {
43+
func (h *handler) saveUploadFiles(fsPrefix string, createDir, overwriteExists bool, aliasSubItems []os.FileInfo, r *http.Request) bool {
4044
errs := []error{}
4145

4246
reader, err := r.MultipartReader()
@@ -54,8 +58,50 @@ func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSu
5458
break
5559
}
5660

57-
filename := part.FileName()
58-
slashIndex := strings.LastIndexAny(filename, "/\\")
61+
partFilename := path.Clean(strings.ReplaceAll(part.FileName(), "\\", "/"))
62+
if partFilename[0] == '/' {
63+
partFilename = partFilename[1:]
64+
}
65+
if len(partFilename) == 0 {
66+
continue
67+
}
68+
69+
slashIndex := strings.LastIndexByte(partFilename, '/')
70+
71+
fsInfix := ""
72+
formname := part.FormName()
73+
if formname == dirFile {
74+
if slashIndex <= 0 {
75+
continue
76+
}
77+
fsInfix = partFilename[0:slashIndex]
78+
} else if formname == innerDirFile { // get file path, strip first level of dir
79+
if slashIndex <= 0 {
80+
continue
81+
}
82+
filepath := partFilename[0:slashIndex]
83+
prefixSlashIndex := strings.IndexByte(filepath, '/')
84+
if prefixSlashIndex > 0 {
85+
fsInfix = filepath[prefixSlashIndex+1:]
86+
}
87+
}
88+
89+
filePrefix := fsPrefix
90+
if len(fsInfix) > 0 {
91+
if !createDir {
92+
errs = append(errs, errors.New("Upload failed: mkdir is not enabled for "+fsPrefix))
93+
continue
94+
}
95+
96+
filePrefix = fsPrefix + "/" + fsInfix
97+
err := os.MkdirAll(filePrefix, 0755)
98+
if err != nil {
99+
errs = append(errs, err)
100+
continue
101+
}
102+
}
103+
104+
filename := partFilename
59105
if slashIndex >= 0 {
60106
filename = filename[slashIndex+1:]
61107
}
@@ -66,7 +112,7 @@ func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSu
66112
isFilenameAliased := containsItem(aliasSubItems, filename)
67113
var fsFilename string
68114
if overwriteExists && !isFilenameAliased {
69-
tryPath := fsPrefix + "/" + filename
115+
tryPath := filePrefix + "/" + filename
70116
var info os.FileInfo
71117
info, err = os.Lstat(tryPath)
72118
if info != nil && !info.IsDir() {
@@ -79,15 +125,15 @@ func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSu
79125
}
80126
}
81127
if len(fsFilename) == 0 {
82-
fsFilename = getAvailableFilename(fsPrefix, filename, isFilenameAliased)
128+
fsFilename = getAvailableFilename(filePrefix, filename, isFilenameAliased)
83129
}
84130
if len(fsFilename) == 0 {
85131
err := errors.New("no available filename for " + filename)
86132
errs = append(errs, err)
87133
continue
88134
}
89135

90-
fsPath := path.Clean(fsPrefix + "/" + fsFilename)
136+
fsPath := path.Clean(filePrefix + "/" + fsFilename)
91137
go h.logUpload(filename, fsPath, r)
92138
file, err := os.OpenFile(fsPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
93139
if err != nil {

test/case/010.upload.bash

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,71 @@
11
#!/bin/bash
22

33
cleanup() {
4-
rm -f "$fs"/uploaded/[12]/*.tmp
4+
rm -rf "$fs"/uploaded/[12]/{*.tmp,*/}
55
}
66

77
source "$root"/lib.bash
88

9-
"$ghfs" -l 3003 -r "$fs"/uploaded --upload /1 --upload-dir "$fs"/uploaded/2 &
9+
"$ghfs" -l 3003 -r "$fs"/uploaded --upload /1 --upload-dir "$fs"/uploaded/2 --mkdir /2 2>/dev/null &
1010
sleep 0.05 # wait server ready
1111
cleanup
1212

13-
content1='uploaded/1/uploaded.tmp'
14-
curl_upload_content 'http://127.0.0.1:3003/1?upload' files "$content1" uploaded.tmp
15-
uploaded1=$(cat "$fs"/uploaded/1/uploaded.tmp)
16-
assert "$uploaded1" "$content1"
13+
# file upload to /1 - valid
14+
content='uploaded/1/uploaded.tmp'
15+
curl_upload_content 'http://127.0.0.1:3003/1?upload' file "$content" uploaded.tmp
16+
uploaded=$(cat "$fs"/uploaded/1/uploaded.tmp)
17+
assert "$uploaded" "$content"
1718

18-
content2='uploaded/2/uploaded.tmp'
19-
curl_upload_content 'http://127.0.0.1:3003/2?upload' files "$content2" uploaded.tmp
20-
uploaded2=$(cat "$fs"/uploaded/2/uploaded.tmp)
21-
assert "$uploaded2" "$content2"
19+
# file upload to /2 - valid
20+
content='uploaded/2/uploaded.tmp'
21+
curl_upload_content 'http://127.0.0.1:3003/2?upload' file "$content" uploaded.tmp
22+
uploaded=$(cat "$fs"/uploaded/2/uploaded.tmp)
23+
assert "$uploaded" "$content"
24+
25+
26+
# dir file upload to /1 - INVALID
27+
content='upload/1/dir/file'
28+
curl_upload_content 'http://127.0.0.1:3003/1?upload' dirfile "$content" dir/uploaded.tmp
29+
[ ! -e "$fs"/uploaded/1/dir/uploaded.tmp ] || fail "/uploaded/1/dir/uploaded.tmp should not be exists"
30+
31+
# dir file upload to /2 - valid
32+
content='upload/2/dir/file'
33+
curl_upload_content 'http://127.0.0.1:3003/2?upload' dirfile "$content" dir/uploaded.tmp
34+
[ -e "$fs"/uploaded/2/dir/uploaded.tmp ] || fail "/uploaded/2/dir/uploaded.tmp should be exists"
35+
uploaded=$(cat "$fs"/uploaded/2/dir/uploaded.tmp)
36+
assert "$uploaded" "$content"
37+
38+
# sub dir file upload to /2 - valid
39+
content='upload/2/dir/sub/file'
40+
curl_upload_content 'http://127.0.0.1:3003/2?upload' dirfile "$content" dir/sub/uploaded.tmp
41+
[ -e "$fs"/uploaded/2/dir/sub/uploaded.tmp ] || fail "/uploaded/2/dir/sub/uploaded.tmp should be exists"
42+
uploaded=$(cat "$fs"/uploaded/2/dir/sub/uploaded.tmp)
43+
assert "$uploaded" "$content"
44+
45+
46+
# inner dir file upload to /1 - valid
47+
content='upload/1/idir/file'
48+
curl_upload_content 'http://127.0.0.1:3003/1?upload' innerdirfile "$content" idir/iuploaded.tmp
49+
uploaded=$(cat "$fs"/uploaded/1/iuploaded.tmp)
50+
assert "$uploaded" "$content"
51+
52+
# inner sub dir file upload to /1 - INVALID
53+
content='upload/1/idir/isub/file'
54+
curl_upload_content 'http://127.0.0.1:3003/1?upload' innerdirfile "$content" idir/isub/iuploaded.tmp
55+
[ ! -e "$fs"/uploaded/2/isub/iuploaded.tmp ] || fail "/uploaded/2/isub/iuploaded.tmp should not be exists"
56+
57+
# inner dir file upload to /2 - valid
58+
content='upload/2/idir/file'
59+
curl_upload_content 'http://127.0.0.1:3003/2?upload' innerdirfile "$content" idir/iuploaded.tmp
60+
uploaded=$(cat "$fs"/uploaded/2/iuploaded.tmp)
61+
assert "$uploaded" "$content"
62+
63+
# inner sub dir file upload to /2 - valid
64+
content='upload/2/idir/isub/file'
65+
curl_upload_content 'http://127.0.0.1:3003/2?upload' innerdirfile "$content" idir/isub/iuploaded.tmp
66+
[ -e "$fs"/uploaded/2/isub/iuploaded.tmp ] || fail "/uploaded/2/isub/iuploaded.tmp should be exists"
67+
uploaded=$(cat "$fs"/uploaded/2/isub/iuploaded.tmp)
68+
assert "$uploaded" "$content"
2269

2370
cleanup
2471
jobs -p | xargs kill

0 commit comments

Comments
 (0)