forked from kataras/iris
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
171 lines (134 loc) · 3.7 KB
/
main.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package main
import (
"image/jpeg"
"image/png"
"io"
"os"
"path"
"path/filepath"
"strings"
"sync"
"github.com/kataras/iris"
"github.com/nfnt/resize"
)
// $ go get -u github.com/nfnt/resize
const uploadsDir = "./public/uploads/"
type uploadedFile struct {
// {name: "", size: } are the dropzone's only requirements.
Name string `json:"name"`
Size int64 `json:"size"`
}
type uploadedFiles struct {
dir string
items []uploadedFile
mu sync.RWMutex // slices are safe but RWMutex is a good practise for you.
}
func scanUploads(dir string) *uploadedFiles {
f := new(uploadedFiles)
lindex := dir[len(dir)-1]
if lindex != os.PathSeparator && lindex != '/' {
dir += string(os.PathSeparator)
}
// create directories if necessary
// and if, then return empty uploaded files; skipping the scan.
if err := os.MkdirAll(dir, os.FileMode(0666)); err != nil {
return f
}
// otherwise scan the given "dir" for files.
f.scan(dir)
return f
}
func (f *uploadedFiles) scan(dir string) {
f.dir = dir
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
// if it's directory or a thumbnail we saved earlier, skip it.
if info.IsDir() || strings.HasPrefix(info.Name(), "thumbnail_") {
return nil
}
f.add(info.Name(), info.Size())
return nil
})
}
func (f *uploadedFiles) add(name string, size int64) uploadedFile {
f.mu.Lock()
uf := uploadedFile{
Name: name,
Size: size,
}
f.items = append(f.items, uf)
f.mu.Unlock()
return uf
}
func (f *uploadedFiles) createThumbnail(uf uploadedFile) {
file, err := os.Open(path.Join(f.dir, uf.Name))
if err != nil {
return
}
defer file.Close()
name := strings.ToLower(uf.Name)
out, err := os.OpenFile(f.dir+"thumbnail_"+uf.Name,
os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return
}
defer out.Close()
if strings.HasSuffix(name, ".jpg") {
// decode jpeg into image.Image
img, err := jpeg.Decode(file)
if err != nil {
return
}
// write new image to file
resized := resize.Thumbnail(180, 180, img, resize.Lanczos3)
jpeg.Encode(out, resized,
&jpeg.Options{Quality: jpeg.DefaultQuality})
} else if strings.HasSuffix(name, ".png") {
img, err := png.Decode(file)
if err != nil {
return
}
// write new image to file
resized := resize.Thumbnail(180, 180, img, resize.Lanczos3) // slower but better res
png.Encode(out, resized)
}
// and so on... you got the point, this code can be simplify, as a practise.
}
func main() {
app := iris.New()
app.RegisterView(iris.HTML("./views", ".html"))
app.StaticWeb("/public", "./public")
app.Get("/", func(ctx iris.Context) {
ctx.View("upload.html")
})
files := scanUploads(uploadsDir)
app.Get("/uploads", func(ctx iris.Context) {
ctx.JSON(files.items)
})
app.Post("/upload", iris.LimitRequestBodySize(10<<20), func(ctx iris.Context) {
// Get the file from the dropzone request
file, info, err := ctx.FormFile("file")
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Application().Logger().Warnf("Error while uploading: %v", err.Error())
return
}
defer file.Close()
fname := info.Filename
// Create a file with the same name
// assuming that you have a folder named 'uploads'
out, err := os.OpenFile(uploadsDir+fname,
os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Application().Logger().Warnf("Error while preparing the new file: %v", err.Error())
return
}
defer out.Close()
io.Copy(out, file)
// optionally, add that file to the list in order to be visible when refresh.
uploadedFile := files.add(fname, info.Size)
go files.createThumbnail(uploadedFile)
})
// start the server at http://localhost:8080
app.Run(iris.Addr(":8080"))
}