|
8 | 8 | "encoding/xml"
|
9 | 9 | "errors"
|
10 | 10 | "fmt"
|
| 11 | + "mime/multipart" |
11 | 12 | "net/http"
|
12 | 13 | "reflect"
|
13 | 14 | "strconv"
|
@@ -90,14 +91,22 @@ func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
|
90 | 91 | }
|
91 | 92 | return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
92 | 93 | }
|
93 |
| - case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm): |
| 94 | + case strings.HasPrefix(ctype, MIMEApplicationForm): |
94 | 95 | params, err := c.FormParams()
|
95 | 96 | if err != nil {
|
96 | 97 | return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
97 | 98 | }
|
98 | 99 | if err = b.bindData(i, params, "form"); err != nil {
|
99 | 100 | return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
|
100 | 101 | }
|
| 102 | + case strings.HasPrefix(ctype, MIMEMultipartForm): |
| 103 | + params, err := c.MultipartForm() |
| 104 | + if err != nil { |
| 105 | + return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err) |
| 106 | + } |
| 107 | + if err = b.bindData(i, params.Value, "form", params.File); err != nil { |
| 108 | + return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err) |
| 109 | + } |
101 | 110 | default:
|
102 | 111 | return ErrUnsupportedMediaType
|
103 | 112 | }
|
@@ -132,8 +141,8 @@ func (b *DefaultBinder) Bind(i interface{}, c Context) (err error) {
|
132 | 141 | }
|
133 | 142 |
|
134 | 143 | // bindData will bind data ONLY fields in destination struct that have EXPLICIT tag
|
135 |
| -func (b *DefaultBinder) bindData(destination interface{}, data map[string][]string, tag string) error { |
136 |
| - if destination == nil || len(data) == 0 { |
| 144 | +func (b *DefaultBinder) bindData(destination interface{}, data map[string][]string, tag string, files ...map[string][]*multipart.FileHeader) error { |
| 145 | + if destination == nil || (len(data) == 0 && len(files) == 0) { |
137 | 146 | return nil
|
138 | 147 | }
|
139 | 148 | typ := reflect.TypeOf(destination).Elem()
|
@@ -209,6 +218,37 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
209 | 218 | continue
|
210 | 219 | }
|
211 | 220 |
|
| 221 | + // Handle multiple file uploads ([]*multipart.FileHeader, *multipart.FileHeader, []multipart.FileHeader) |
| 222 | + if len(files) > 0 { |
| 223 | + for _, fileMap := range files { |
| 224 | + fileHeaders, exists := fileMap[inputFieldName] |
| 225 | + if exists { |
| 226 | + if structField.Type() == reflect.TypeOf([]*multipart.FileHeader(nil)) { |
| 227 | + structField.Set(reflect.ValueOf(fileHeaders)) |
| 228 | + continue |
| 229 | + } else if structField.Type() == reflect.TypeOf([]multipart.FileHeader(nil)) { |
| 230 | + var headers []multipart.FileHeader |
| 231 | + for _, fileHeader := range fileHeaders { |
| 232 | + headers = append(headers, *fileHeader) |
| 233 | + } |
| 234 | + structField.Set(reflect.ValueOf(headers)) |
| 235 | + continue |
| 236 | + } else if structField.Type() == reflect.TypeOf(&multipart.FileHeader{}) { |
| 237 | + |
| 238 | + if len(fileHeaders) > 0 { |
| 239 | + structField.Set(reflect.ValueOf(fileHeaders[0])) |
| 240 | + } |
| 241 | + continue |
| 242 | + } else if structField.Type() == reflect.TypeOf(multipart.FileHeader{}) { |
| 243 | + if len(fileHeaders) > 0 { |
| 244 | + structField.Set(reflect.ValueOf(*fileHeaders[0])) |
| 245 | + } |
| 246 | + continue |
| 247 | + } |
| 248 | + } |
| 249 | + } |
| 250 | + } |
| 251 | + |
212 | 252 | inputValue, exists := data[inputFieldName]
|
213 | 253 | if !exists {
|
214 | 254 | // Go json.Unmarshal supports case insensitive binding. However the
|
|
0 commit comments