-
Notifications
You must be signed in to change notification settings - Fork 0
/
upload-handler.go
123 lines (101 loc) · 2.58 KB
/
upload-handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package gfs
import (
"errors"
"io"
"log"
"net/http"
"os"
"path"
"strings"
)
type UploadHandler struct {
responseHandler
config *Config
clientErrorHandler *ClientErrorHandler
}
var (
ErrNoUploadingUp = errors.New("Unable to upload up outside the <serve> directory.")
ErrNoFilenameProvided = errors.New("No filename provided. Cannot accept upload")
ErrUnknownContentType = errors.New("Unknown upload content type. Cannot proceed.")
)
func isUploadClientError(err error) bool {
return err == ErrNoUploadingUp ||
err == ErrNoFilenameProvided ||
err == ErrUnknownContentType
}
func (h *UploadHandler) Handle(writer http.ResponseWriter, request *http.Request, responseFormat string) error {
ct := getContentType(request)
if ct == "multipart/form-data" {
uploadPath := request.FormValue("path")
err := request.ParseMultipartForm(1 << 20) // 1MB
if err != nil {
return err
}
files, ok := request.MultipartForm.File["uploadfiles"]
if !ok {
log.Println("No upload files")
log.Println(request.MultipartForm)
}
log.Println(files)
for i := range files {
err := func(i int) error {
fileRef := files[i]
log.Println("Handling file", fileRef.Filename)
file, err := fileRef.Open()
if err != nil {
return err
}
defer file.Close()
return h.uploadFile(path.Join(uploadPath, fileRef.Filename), file)
}(i)
if err != nil {
return err
}
}
http.Redirect(writer, request, uploadPath, http.StatusFound)
return nil
} else if ct == FormatOctetStream {
filename := request.URL.Query().Get("filename")
if filename == "" {
return ErrNoFilenameProvided
}
defer request.Body.Close()
err := h.uploadFile(filename, request.Body)
if err != nil {
return err
}
writer.WriteHeader(http.StatusAccepted)
return nil
} else {
return ErrUnknownContentType
}
}
func (h *UploadHandler) uploadFile(filename string, file io.Reader) error {
outputPath := path.Join(h.config.Serve, filename)
log.Println("outputPath", outputPath)
// Ensure that it's not possible to upload "upwards" in the tree
if !strings.HasPrefix(outputPath, h.config.Serve) {
return ErrNoUploadingUp
}
err := os.MkdirAll(path.Dir(outputPath), os.ModePerm)
if err != nil {
return err
}
dst, err := os.Create(outputPath)
if err != nil {
return err
}
defer dst.Close()
_, err = io.Copy(dst, file)
return err
}
func GetUploadHandler(config *Config) (*UploadHandler, error) {
chl, err := GetClientErrorHandler()
if err != nil {
return nil, err
}
return &UploadHandler{
config: config,
clientErrorHandler: chl,
}, nil
}