Skip to content

Commit 69dc939

Browse files
committed
first commit
0 parents  commit 69dc939

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

fileupload.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package fileupload
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"io"
7+
"mime/multipart"
8+
"net/http"
9+
"net/url"
10+
"os"
11+
"strconv"
12+
13+
"github.com/kennygrant/sanitize"
14+
)
15+
16+
type File struct {
17+
FileName string `json:"FileName"`
18+
URL string `json:"URL"`
19+
}
20+
21+
func FromRequest(req *http.Request, path string) (string, string, error) {
22+
req.ParseMultipartForm(32)
23+
file, handler, err := req.FormFile("file")
24+
if err != nil {
25+
return "", "", err
26+
}
27+
defer file.Close()
28+
29+
filename := getValidFileName(path, handler.Filename)
30+
fullpath := path + filename
31+
f, err := os.OpenFile(fullpath, os.O_WRONLY|os.O_CREATE, 0666)
32+
if err != nil {
33+
return "", "", err
34+
}
35+
defer f.Close()
36+
37+
_, err = io.Copy(f, file)
38+
if err != nil {
39+
return "", "", err
40+
}
41+
return filename, fullpath, nil
42+
}
43+
44+
func FromBuffer(name string, path string, body io.Reader) (string, string, error) {
45+
filename := getValidFileName(path, name)
46+
fullpath := path + filename
47+
f, err := os.OpenFile(fullpath, os.O_RDWR|os.O_CREATE, 0666)
48+
if err != nil {
49+
return "", "", err
50+
}
51+
defer f.Close()
52+
// we read from tee reader as it hasn't already done its scan
53+
_, err = io.Copy(f, body)
54+
if err != nil {
55+
return "", "", err
56+
}
57+
return filename, fullpath, nil
58+
}
59+
60+
func getValidFileName(path string, filename string) string {
61+
return getValidFileNameWithDupIndex(path, filename, 0)
62+
}
63+
64+
func getValidFileNameWithDupIndex(path string, filename string, duplicateIndex int) string {
65+
filename = sanitize.Path(filename)
66+
dupStr := ""
67+
if duplicateIndex > 0 {
68+
dupStr = "" + strconv.Itoa(duplicateIndex) + "-"
69+
}
70+
fullpath := path + dupStr + filename
71+
72+
// path doesn't exist so we can return this path
73+
if _, err := os.Stat(fullpath); os.IsNotExist(err) {
74+
return dupStr + filename
75+
}
76+
77+
//otherwise increase file index and
78+
duplicateIndex++
79+
return getValidFileNameWithDupIndex(path, filename, duplicateIndex)
80+
}
81+
82+
type operation struct {
83+
Operation string `json:"operation"`
84+
Params map[string]interface{} `json:"params"`
85+
}
86+
87+
type operations struct {
88+
Ops []*operation
89+
}
90+
91+
func (o *operation) addParam(key string, val interface{}) {
92+
if o.Params == nil {
93+
o.Params = make(map[string]interface{})
94+
}
95+
o.Params[key] = val
96+
}
97+
98+
func (o *operations) add(op string) {
99+
if o.Ops == nil {
100+
o.Ops = make([]*operation, 0)
101+
}
102+
o.Ops = append(o.Ops, &operation{
103+
Operation: op,
104+
})
105+
}
106+
107+
func (o *operations) last() *operation {
108+
return o.Ops[len(o.Ops)-1]
109+
}
110+
111+
func ProcessedImageFromRequest(req *http.Request, imageType string, maxWidth int, quality int, convert bool) (*http.Response, error) {
112+
err := req.ParseMultipartForm(32)
113+
if err != nil {
114+
return nil, err
115+
}
116+
file, _, err := req.FormFile("file")
117+
if err != nil {
118+
return nil, err
119+
}
120+
defer file.Close()
121+
122+
return ProcessedImage(file, imageType, maxWidth, quality, convert)
123+
}
124+
125+
func ProcessedImage(r io.Reader, imageType string, maxWidth int, quality int, convert bool) (*http.Response, error) {
126+
ops := &operations{}
127+
128+
originalImageType := "jpg"
129+
if convert {
130+
ops.add("convert")
131+
132+
// converting
133+
if imageType == "jpg" {
134+
imageType = "jpeg"
135+
originalImageType = "png"
136+
} else if imageType == "png" {
137+
originalImageType = "jpg"
138+
}
139+
ops.last().addParam("type", imageType)
140+
}
141+
142+
ops.add("fit")
143+
// ops.last().addParam("rotate", "0")
144+
// ops.last().addParam("background", "255,255,255")
145+
ops.last().addParam("width", maxWidth) //absolute max
146+
ops.last().addParam("height", maxWidth) // dont need its ratio based
147+
// ops.last().addParam("stripmeta", true) // dont need its ratio based
148+
ops.last().addParam("quality", quality)
149+
// ops.last().addParam("compression", quality)
150+
bOps, err := json.Marshal(ops.Ops)
151+
if err != nil {
152+
return nil, err
153+
}
154+
endpoint := "https://images.nerdy.co.nz/pipeline?operations=" + url.QueryEscape(string(bOps))
155+
// endpoint = "https://images.nerdy.co.nz/fit?width=200&height=200"
156+
157+
var b bytes.Buffer
158+
w := multipart.NewWriter(&b)
159+
fw, err := w.CreateFormFile("file", "filename_placeholder."+originalImageType)
160+
if err != nil {
161+
return nil, err
162+
}
163+
_, err = io.Copy(fw, r)
164+
if err != nil {
165+
return nil, err
166+
}
167+
err = w.Close()
168+
if err != nil {
169+
return nil, err
170+
}
171+
172+
req, err := http.NewRequest("POST", endpoint, &b)
173+
if err != nil {
174+
return nil, err
175+
}
176+
req.Header.Set("Content-Type", w.FormDataContentType())
177+
178+
client := &http.Client{}
179+
res, err := client.Do(req)
180+
if err != nil {
181+
return nil, err
182+
}
183+
184+
return res, nil
185+
}

0 commit comments

Comments
 (0)