1
+ package main
2
+
3
+ import (
4
+ "crypto/sha1"
5
+ "encoding/hex"
6
+ "errors"
7
+ "fmt"
8
+ "github.com/graphql-go/graphql"
9
+ handler "github.com/jpascal/graphql-upload"
10
+ uuid "github.com/satori/go.uuid"
11
+ "io"
12
+ "io/ioutil"
13
+ "log"
14
+ "net/http"
15
+ "os"
16
+ "path"
17
+ )
18
+
19
+ var UploadType = graphql .NewScalar (graphql.ScalarConfig {
20
+ Name : "Upload" ,
21
+ Description : "Scalar upload object" ,
22
+ })
23
+
24
+ type FileWrapper struct {
25
+ File * os.File
26
+ Name string
27
+ }
28
+
29
+ var File = graphql .NewObject (graphql.ObjectConfig {
30
+ Name : "File" ,
31
+ Description : "File object" ,
32
+ Fields : graphql.Fields {
33
+ "name" : & graphql.Field {
34
+ Type : graphql .String ,
35
+ Resolve : func (params graphql.ResolveParams ) (interface {}, error ) {
36
+ file := params .Source .(* FileWrapper )
37
+ name := path .Base (file .Name )
38
+
39
+ return name , nil
40
+ },
41
+ },
42
+ "hash" : & graphql.Field {
43
+ Type : graphql .String ,
44
+ Resolve : func (params graphql.ResolveParams ) (interface {}, error ) {
45
+ file := params .Source .(* FileWrapper )
46
+ if data , err := ioutil .ReadAll (file .File ); err == nil {
47
+ fileHash := sha1 .Sum (data )
48
+
49
+ return hex .EncodeToString (fileHash [:]), nil
50
+ } else {
51
+ return nil , err
52
+ }
53
+
54
+ },
55
+ },
56
+ "size" : & graphql.Field {
57
+ Type : graphql .Int ,
58
+ Resolve : func (params graphql.ResolveParams ) (interface {}, error ) {
59
+ file := params .Source .(* FileWrapper )
60
+ if info , err := file .File .Stat (); err != nil {
61
+ return nil , err
62
+ } else {
63
+ return info .Size (), nil
64
+ }
65
+ },
66
+ },
67
+ },
68
+ })
69
+
70
+ func main () {
71
+ schema , err := graphql .NewSchema (
72
+ graphql.SchemaConfig {
73
+ Query : graphql .NewObject (
74
+ graphql.ObjectConfig {
75
+ Name : "Query" ,
76
+ Fields : graphql.Fields {
77
+ "file" : & graphql.Field {
78
+ Type : File ,
79
+ Args : graphql.FieldConfigArgument {
80
+ "id" : & graphql.ArgumentConfig {
81
+ Type : graphql .NewNonNull (graphql .String ),
82
+ },
83
+ },
84
+ Resolve : func (params graphql.ResolveParams ) (interface {}, error ) {
85
+ if fileId , ok := params .Args ["id" ].(string ); ok {
86
+ fileUuid , err := uuid .FromString (fileId )
87
+ if err != nil {
88
+ return nil , err
89
+ }
90
+
91
+ file , err := os .Open ("tmp/" + fileUuid .String ())
92
+ if err != nil {
93
+ return nil , err
94
+ }
95
+
96
+ return & FileWrapper {File : file , Name : fileUuid .String ()}, nil
97
+ } else {
98
+ return nil , errors .New ("file id is not provided" )
99
+ }
100
+ },
101
+ },
102
+ },
103
+ }),
104
+ Mutation : graphql .NewObject (
105
+ graphql.ObjectConfig {
106
+ Name : "Mutation" ,
107
+ Fields : graphql.Fields {
108
+ "upload" : & graphql.Field {
109
+ Type : graphql .NewNonNull (graphql .String ),
110
+ Args : graphql.FieldConfigArgument {
111
+ "file" : & graphql.ArgumentConfig {
112
+ Type : graphql .NewNonNull (UploadType ),
113
+ },
114
+ },
115
+ Resolve : func (params graphql.ResolveParams ) (interface {}, error ) {
116
+ upload , uploadPresent := params .Args ["file" ].(handler.File )
117
+ if uploadPresent {
118
+ id := uuid .NewV4 ().String ()
119
+ targetFile , err := os .Create ("tmp/" + id )
120
+ if err != nil {
121
+ return nil , err
122
+ }
123
+
124
+ defer targetFile .Close ()
125
+ nBytes , err := io .Copy (targetFile , upload .File )
126
+ if err != nil {
127
+ return nil , err
128
+ }
129
+
130
+ log .Println ("File saved nBytes: " , nBytes )
131
+ return id , nil
132
+ } else {
133
+ return nil , errors .New ("no file found in request" )
134
+ }
135
+
136
+ },
137
+ },
138
+ "uploadMulti" : & graphql.Field {
139
+ Type : graphql .NewNonNull (graphql .NewList (graphql .NewNonNull (graphql .String ))),
140
+ Args : graphql.FieldConfigArgument {
141
+ "files" : & graphql.ArgumentConfig {
142
+ Type : graphql .NewNonNull (graphql .NewList (graphql .NewNonNull (UploadType ))),
143
+ },
144
+ },
145
+ Resolve : func (params graphql.ResolveParams ) (interface {}, error ) {
146
+ uploads , uploadPresent := params .Args ["files" ].([]interface {})
147
+ if uploadPresent {
148
+ var result []string
149
+ for i , uploadItem := range uploads {
150
+
151
+ upload , ok := uploadItem .(handler.File )
152
+ if ! ok {
153
+ return nil , errors .New (fmt .Sprintf ("type of file %d is wrong" , i ))
154
+ }
155
+
156
+ id := uuid .NewV4 ().String ()
157
+ targetFile , err := os .Create ("tmp/" + id )
158
+ if err != nil {
159
+ return nil , err
160
+ }
161
+
162
+ defer targetFile .Close ()
163
+ nBytes , err := io .Copy (targetFile , upload .File )
164
+ if err != nil {
165
+ return nil , err
166
+ }
167
+
168
+ log .Println ("File saved nBytes: " , nBytes )
169
+ result = append (result , id )
170
+ }
171
+
172
+ return result , nil
173
+ } else {
174
+ return nil , errors .New ("no file found in request" )
175
+ }
176
+
177
+ },
178
+ },
179
+ },
180
+ }),
181
+ })
182
+ if err != nil {
183
+ panic (err )
184
+ }
185
+
186
+ server := & http.Server {Addr : "0.0.0.0:5000" , Handler : handler .New (func (request * handler.Request ) interface {} {
187
+ return graphql .Do (graphql.Params {
188
+ RequestString : request .Query ,
189
+ OperationName : request .OperationName ,
190
+ VariableValues : request .Variables ,
191
+ Schema : schema ,
192
+ Context : request .Context ,
193
+ })
194
+ }, & handler.Config {
195
+ MaxBodySize : 1024 ,
196
+ }),
197
+ }
198
+ server .ListenAndServe ()
199
+ }
0 commit comments