@@ -85,30 +85,51 @@ func (v MimeTypeValidator) Validate(fh *multipart.FileHeader, location string) (
8585 }
8686}
8787
88- func (m * MultipartFormFiles [T ]) readFile (
89- fh * multipart.FileHeader ,
90- location string ,
91- validator MimeTypeValidator ,
92- ) (FormFile , * ErrorDetail ) {
93- f , err := fh .Open ()
94- if err != nil {
95- return FormFile {}, & ErrorDetail {Message : "Failed to open file" , Location : location }
96- }
97- contentType , validationErr := validator .Validate (fh , location )
98- if validationErr != nil {
99- return FormFile {}, validationErr
88+ func (m * MultipartFormFiles [T ]) Data () * T {
89+ return m .data
90+ }
91+
92+ // Decodes multipart.Form data into *T, returning []*ErrorDetail if any
93+ // Schema is used to check for validation constraints
94+ func (m * MultipartFormFiles [T ]) Decode (opMediaType * MediaType ) []error {
95+ var (
96+ dataType = reflect .TypeOf (m .data ).Elem ()
97+ value = reflect .New (dataType )
98+ errors []error
99+ )
100+ for i := 0 ; i < dataType .NumField (); i ++ {
101+ field := value .Elem ().Field (i )
102+ structField := dataType .Field (i )
103+ key := structField .Tag .Get ("form" )
104+ if key == "" {
105+ key = structField .Name
106+ }
107+ fileHeaders := m .Form .File [key ]
108+ switch {
109+ case field .Type () == reflect .TypeOf (FormFile {}):
110+ file , err := readSingleFile (fileHeaders , key , opMediaType )
111+ if err != nil {
112+ errors = append (errors , err )
113+ continue
114+ }
115+ field .Set (reflect .ValueOf (file ))
116+ case field .Type () == reflect .TypeOf ([]FormFile {}):
117+ files , errs := readMultipleFiles (fileHeaders , key , opMediaType )
118+ if errs != nil {
119+ errors = append (errors , errs ... )
120+ continue
121+ }
122+ field .Set (reflect .ValueOf (files ))
123+
124+ default :
125+ continue
126+ }
100127 }
101- return FormFile {
102- File : f ,
103- ContentType : contentType ,
104- IsSet : true ,
105- Size : fh .Size ,
106- Filename : fh .Filename ,
107- }, nil
128+ m .data = value .Interface ().(* T )
129+ return errors
108130}
109131
110- func (m * MultipartFormFiles [T ]) readSingleFile (key string , opMediaType * MediaType ) (FormFile , * ErrorDetail ) {
111- fileHeaders := m .Form .File [key ]
132+ func readSingleFile (fileHeaders []* multipart.FileHeader , key string , opMediaType * MediaType ) (FormFile , * ErrorDetail ) {
112133 if len (fileHeaders ) == 0 {
113134 if opMediaType .Schema .requiredMap [key ] {
114135 return FormFile {}, & ErrorDetail {Message : "File required" , Location : key }
@@ -117,16 +138,15 @@ func (m *MultipartFormFiles[T]) readSingleFile(key string, opMediaType *MediaTyp
117138 }
118139 } else if len (fileHeaders ) == 1 {
119140 validator := NewMimeTypeValidator (opMediaType .Encoding [key ])
120- return m . readFile (fileHeaders [0 ], key , validator )
141+ return readFile (fileHeaders [0 ], key , validator )
121142 }
122143 return FormFile {}, & ErrorDetail {
123144 Message : "Multiple files received but only one was expected" ,
124145 Location : key ,
125146 }
126147}
127148
128- func (m * MultipartFormFiles [T ]) readMultipleFiles (key string , opMediaType * MediaType ) ([]FormFile , []error ) {
129- fileHeaders := m .Form .File [key ]
149+ func readMultipleFiles (fileHeaders []* multipart.FileHeader , key string , opMediaType * MediaType ) ([]FormFile , []error ) {
130150 var (
131151 files = make ([]FormFile , len (fileHeaders ))
132152 errors []error
@@ -136,7 +156,7 @@ func (m *MultipartFormFiles[T]) readMultipleFiles(key string, opMediaType *Media
136156 }
137157 validator := NewMimeTypeValidator (opMediaType .Encoding [key ])
138158 for i , fh := range fileHeaders {
139- file , err := m . readFile (
159+ file , err := readFile (
140160 fh ,
141161 fmt .Sprintf ("%s[%d]" , key , i ),
142162 validator ,
@@ -150,47 +170,26 @@ func (m *MultipartFormFiles[T]) readMultipleFiles(key string, opMediaType *Media
150170 return files , errors
151171}
152172
153- func (m * MultipartFormFiles [T ]) Data () * T {
154- return m .data
155- }
156-
157- // Decodes multipart.Form data into *T, returning []*ErrorDetail if any
158- // Schema is used to check for validation constraints
159- func (m * MultipartFormFiles [T ]) Decode (opMediaType * MediaType ) []error {
160- var (
161- dataType = reflect .TypeOf (m .data ).Elem ()
162- value = reflect .New (dataType )
163- errors []error
164- )
165- for i := 0 ; i < dataType .NumField (); i ++ {
166- field := value .Elem ().Field (i )
167- structField := dataType .Field (i )
168- key := structField .Tag .Get ("form" )
169- if key == "" {
170- key = structField .Name
171- }
172- switch {
173- case field .Type () == reflect .TypeOf (FormFile {}):
174- file , err := m .readSingleFile (key , opMediaType )
175- if err != nil {
176- errors = append (errors , err )
177- continue
178- }
179- field .Set (reflect .ValueOf (file ))
180- case field .Type () == reflect .TypeOf ([]FormFile {}):
181- files , errs := m .readMultipleFiles (key , opMediaType )
182- if errs != nil {
183- errors = append (errors , errs ... )
184- continue
185- }
186- field .Set (reflect .ValueOf (files ))
187-
188- default :
189- continue
190- }
173+ func readFile (
174+ fh * multipart.FileHeader ,
175+ location string ,
176+ validator MimeTypeValidator ,
177+ ) (FormFile , * ErrorDetail ) {
178+ f , err := fh .Open ()
179+ if err != nil {
180+ return FormFile {}, & ErrorDetail {Message : "Failed to open file" , Location : location }
191181 }
192- m .data = value .Interface ().(* T )
193- return errors
182+ contentType , validationErr := validator .Validate (fh , location )
183+ if validationErr != nil {
184+ return FormFile {}, validationErr
185+ }
186+ return FormFile {
187+ File : f ,
188+ ContentType : contentType ,
189+ IsSet : true ,
190+ Size : fh .Size ,
191+ Filename : fh .Filename ,
192+ }, nil
194193}
195194
196195func formDataFieldName (f reflect.StructField ) string {
@@ -208,7 +207,7 @@ func multiPartFormFileSchema(t reflect.Type) *Schema {
208207 Properties : make (map [string ]* Schema , nFields ),
209208 requiredMap : make (map [string ]bool , nFields ),
210209 }
211- requiredFields := make ([]string , nFields )
210+ requiredFields := make ([]string , 0 , nFields )
212211 for i := 0 ; i < nFields ; i ++ {
213212 f := t .Field (i )
214213 name := formDataFieldName (f )
@@ -227,7 +226,7 @@ func multiPartFormFileSchema(t reflect.Type) *Schema {
227226 }
228227
229228 if _ , ok := f .Tag .Lookup ("required" ); ok && boolTag (f , "required" , false ) {
230- requiredFields [ i ] = name
229+ requiredFields = append ( requiredFields , name )
231230 schema .requiredMap [name ] = true
232231 }
233232 }
0 commit comments