-
Notifications
You must be signed in to change notification settings - Fork 0
/
upload.go
131 lines (112 loc) · 2.57 KB
/
upload.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
package sn
import (
"bytes"
"encoding/json"
"fmt"
"image"
"image/png"
"io"
"mime/multipart"
"net/http"
)
type GetSignedPOST struct {
Url string `json:"url"`
Fields map[string]string `json:"fields"`
}
type GetSignedPOSTResponse struct {
Errors []GqlError `json:"errors"`
Data struct {
GetSignedPOST GetSignedPOST `json:"getSignedPOST"`
} `json:"data"`
}
func (c *Client) UploadImage(img *image.RGBA) (string, error) {
var (
b = img.Bounds()
width = b.Dx()
height = b.Dy()
type_ = "image/png"
size int
)
var imgBuf bytes.Buffer
if err := png.Encode(&imgBuf, img); err != nil {
return "", err
}
size = imgBuf.Len()
// get signed URL for S3 upload
body := GqlBody{
Query: `
mutation getSignedPOST($type: String!, $size: Int!, $width: Int!, $height: Int!, $avatar: Boolean) {
getSignedPOST(type: $type, size: $size, width: $width, height: $height, avatar: $avatar) {
url
fields
}
}`,
Variables: map[string]interface{}{
"type": type_,
"size": size,
"width": width,
"height": height,
"avatar": false,
},
}
resp, err := c.callApi(body)
if err != nil {
return "", err
}
defer resp.Body.Close()
var respBody GetSignedPOSTResponse
err = json.NewDecoder(resp.Body).Decode(&respBody)
if err != nil {
err = fmt.Errorf("error decoding getSignedPOST: %w", err)
return "", err
}
err = c.checkForErrors(respBody.Errors)
if err != nil {
return "", err
}
s3Url := respBody.Data.GetSignedPOST.Url
fields := respBody.Data.GetSignedPOST.Fields
// create multipart form
var (
buf bytes.Buffer
w = multipart.NewWriter(&buf)
fw io.Writer
)
for k, v := range fields {
if fw, err = w.CreateFormField(k); err != nil {
return "", err
}
fw.Write([]byte(v))
}
for k, v := range map[string]string{
"Content-Type": type_,
"Cache-Control": "max-age=31536000",
"acl": "public-read",
} {
if fw, err = w.CreateFormField(k); err != nil {
return "", err
}
fw.Write([]byte(v))
}
if fw, err = w.CreateFormFile("file", "image.png"); err != nil {
return "", err
}
fw.Write(imgBuf.Bytes())
if err = w.Close(); err != nil {
return "", err
}
// upload to S3
var req *http.Request
if req, err = http.NewRequest("POST", s3Url, &buf); err != nil {
return "", err
}
req.Header.Set("Content-Type", w.FormDataContentType())
client := http.DefaultClient
if resp, err = client.Do(req); err != nil {
return "", err
}
defer resp.Body.Close()
imgId := respBody.Data.GetSignedPOST.Fields["key"]
imgUrl := fmt.Sprintf("%s/%s", c.MediaUrl, imgId)
return imgUrl, nil
}