swagger-api / swagger-node

Swagger module for node.js
http://swagger.io
Apache License 2.0
3.97k stars 585 forks source link

req.files must be provided for 'formData' #336

Open ghost opened 8 years ago

ghost commented 8 years ago

For testing purposes i specified incorrect post methods (x-www-form-urlencoded, raw, binary) to handle multipart/form-data. A failed response is expected but an error is thrown rather than being caught by my error handler.

Spec

consumes:
  - application/json 
  - multipart/form-data
  - x-www-form-urlencoded
post:
      operationId: uploadCSV
      description: "Upload comma delimited csv"
      parameters:
        - name: database
          in: query
          type: string
          required: true
        - name: CSVFile
          in: formData
          type: file
          required: true 
      responses:
        200:
          description: "Successfully uploaded csv"
          schema:
              $ref: "#/definitions/successResponse"
        default:
          description: "Error uploading csv"
          schema:
            $ref: "#/definitions/errorResponse"

Stack

Error: req.files must be provided for 'formData' parameters of type 'file'
2016-01-04T17:57:45.055111+00:00 app[web.1]:     at Parameter.getValue (/app/node_modules/sway/lib/types/parameter.js:143:15)
2016-01-04T17:57:45.055111+00:00 app[web.1]:     at /app/node_modules/swagger-node-runner/fittings/swagger_params_parser.js:40:44
2016-01-04T17:57:45.055109+00:00 app[web.1]:
2016-01-04T17:57:45.055112+00:00 app[web.1]:     at Array.forEach (native)
2016-01-04T17:57:45.055112+00:00 app[web.1]:     at /app/node_modules/swagger-node-runner/fittings/swagger_params_parser.js:39:46
2016-01-04T17:57:45.055114+00:00 app[web.1]:     at finishedParseBody (/app/node_modules/swagger-node-runner/fittings/swagger_params_parser.js:125:12)
2016-01-04T17:57:45.055114+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:721:13
2016-01-04T17:57:45.055115+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:52:16
2016-01-04T17:57:45.055116+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:269:32
2016-01-04T17:57:45.055116+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:44:16
2016-01-04T17:57:45.055117+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:718:17
2016-01-04T17:57:45.055118+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:167:37
2016-01-04T17:57:45.055119+00:00 app[web.1]:     at parseText (/app/node_modules/swagger-node-runner/fittings/swagger_params_parser.js:118:60)
2016-01-04T17:57:45.055119+00:00 app[web.1]:     at /app/node_modules/async/lib/async.js:713:13
2016-01-04T17:57:45.055120+00:00 app[web.1]:     at Immediate.iterate [as _onImmediate] (/app/node_modules/async/lib/async.js:262:13)
2016-01-04T17:57:45.055121+00:00 app[web.1]:     at processImmediate [as _immediateCallback] (timers.js:383:17)
amitonkare commented 8 years ago

hey! Whats the solution on this?

ChristianRich commented 8 years ago

You need to use a library like npm multer and add it to your middleware stack. This will catch the file on POST and attach it to the req object as req.files

b4dnewz commented 6 years ago

with multer is working good but only for multiple files multer.fields([{name: 'file'}]) since multer add the req.files property but I can't make it working with single file:

multer.single('file') will create req.file instead of req.files and swagger will throw this err:

Error: req.files must be provided for 'formData' parameters of type 'file'
    at Parameter.getValue (C:\path\to\api\node_modules\sway\lib\types\parameter.js:141:15)

any idea on how to make this work?

summit2020 commented 6 years ago

I got a work around on it. Every http middleware stack runs http request to complete request parser which also declare req.file or req.files as array of files for some http frameworks. Just jump to (C:\path\to\api\node_modules\sway\lib\types\parameter.js:141:15) line number & edit it to req.file where key is file & parameter value will be set to it. It works for sure, thanks!

rahulthakur319 commented 6 years ago

@b4dnewz : This custom middleware worked for me to handle single file upload. If req.file is there it puts it into req.files

app.use(function (req, res, next) {
    if(req.file){
      req.files = req.file  
    }
    next();
  });
b4dnewz commented 6 years ago

@rahulthakur319 nice trick

but I think this issue should be addressed from swagger-node project rather than by users, since multer is the de-facto standard for handling multipart-form-data

it's a pretty simple change:

if (_.isUndefined(req.files)) { // _.isUndefined(req.files) && _.isUndefined(req.file)

}

or even better, by adding in the swagger definition a property to specify if should be threat as multiple or single file upload

Also using req.files[0] it's a legit trick