120 lines
2.5 KiB
JavaScript
120 lines
2.5 KiB
JavaScript
/*!
|
|
* connect-multiparty
|
|
* Copyright(c) 2010 Sencha Inc.
|
|
* Copyright(c) 2011 TJ Holowaychuk
|
|
* Copyright(c) 2013 Andrew Kelley
|
|
* MIT Licensed
|
|
*/
|
|
|
|
'use strict'
|
|
|
|
/**
|
|
* Module dependencies.
|
|
* @private
|
|
*/
|
|
|
|
var createError = require('http-errors')
|
|
var multiparty = require('multiparty');
|
|
var onFinished = require('on-finished');
|
|
var qs = require('qs');
|
|
var typeis = require('type-is');
|
|
|
|
/**
|
|
* Module exports.
|
|
* @public
|
|
*/
|
|
|
|
module.exports = multipart
|
|
|
|
/**
|
|
* Parse multipart/form-data request bodies, providing the parsed
|
|
* object as `req.body` and `req.files`.
|
|
*
|
|
* The options passed are merged with [multiparty](https://github.com/pillarjs/multiparty)'s
|
|
* `Form` object, allowing you to configure the upload directory,
|
|
* size limits, etc. For example if you wish to change the upload
|
|
* dir do the following:
|
|
*
|
|
* app.use(multipart({ uploadDir: path }))
|
|
*
|
|
* @param {Object} options
|
|
* @return {Function}
|
|
* @public
|
|
*/
|
|
|
|
function multipart (options) {
|
|
options = options || {};
|
|
|
|
return function multipart(req, res, next) {
|
|
if (req._body) return next();
|
|
req.body = req.body || {};
|
|
req.files = req.files || {};
|
|
|
|
// ignore GET
|
|
if ('GET' === req.method || 'HEAD' === req.method) return next();
|
|
|
|
// check Content-Type
|
|
if (!typeis(req, 'multipart/form-data')) return next();
|
|
|
|
// flag as parsed
|
|
req._body = true;
|
|
|
|
// parse
|
|
var form = new multiparty.Form(options);
|
|
var data = {};
|
|
var files = {};
|
|
var done = false;
|
|
|
|
function ondata(name, val, data){
|
|
if (Array.isArray(data[name])) {
|
|
data[name].push(val);
|
|
} else if (data[name]) {
|
|
data[name] = [data[name], val];
|
|
} else {
|
|
data[name] = val;
|
|
}
|
|
}
|
|
|
|
form.on('field', function(name, val){
|
|
ondata(name, val, data);
|
|
});
|
|
|
|
form.on('file', function(name, val){
|
|
val.name = val.originalFilename;
|
|
val.type = val.headers['content-type'] || null;
|
|
ondata(name, val, files);
|
|
});
|
|
|
|
form.on('error', function(err){
|
|
if (done) return;
|
|
|
|
done = true;
|
|
|
|
// set status code on error
|
|
var error = createError(400, err)
|
|
|
|
if (!req.readable) return next(error)
|
|
|
|
// read off entire request
|
|
req.resume();
|
|
onFinished(req, function(){
|
|
next(error)
|
|
});
|
|
});
|
|
|
|
form.on('close', function() {
|
|
if (done) return;
|
|
|
|
done = true;
|
|
|
|
// expand names with qs & assign
|
|
req.body = qs.parse(data, { allowDots: true })
|
|
req.files = qs.parse(files, { allowDots: true })
|
|
|
|
next()
|
|
});
|
|
|
|
form.parse(req);
|
|
}
|
|
};
|