processMultipart.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. const Busboy = require('busboy');
  2. const fileFactory = require('./fileFactory');
  3. const memHandler = require('./memHandler');
  4. const tempFileHandler = require('./tempFileHandler');
  5. const processNested = require('./processNested');
  6. const {
  7. isFunc,
  8. buildOptions,
  9. buildFields,
  10. parseFileName
  11. } = require('./utilities');
  12. /**
  13. * Processes multipart request
  14. * Builds a req.body object for fields
  15. * Builds a req.files object for files
  16. * @param {Object} options expressFileupload and Busboy options
  17. * @param {Object} req Express request object
  18. * @param {Object} res Express response object
  19. * @param {Function} next Express next method
  20. * @return {void}
  21. */
  22. module.exports = (options, req, res, next) => {
  23. req.files = null;
  24. // Build busboy options and init busboy instance.
  25. let busboyOptions = buildOptions(options, {headers: req.headers});
  26. let busboy = new Busboy(busboyOptions);
  27. // Build multipart req.body fields
  28. busboy.on('field', (fieldname, val) => req.body = buildFields(req.body, fieldname, val));
  29. // Build req.files fields
  30. busboy.on('file', (fieldname, file, filename, encoding, mime) => {
  31. const {dataHandler, getFilePath, getFileSize, getHash, complete, cleanup} = options.useTempFiles
  32. ? tempFileHandler(options, fieldname, filename)
  33. : memHandler(options, fieldname, filename);
  34. file.on('limit', () => {
  35. // Run user defined limit handler if it has been set.
  36. if (isFunc(options.limitHandler)){
  37. return options.limitHandler(req, res, next);
  38. }
  39. // Close connection with 413 code if abortOnLimit set(default: false).
  40. if (options.abortOnLimit) {
  41. res.writeHead(413, { Connection: 'close' });
  42. res.end(options.responseOnLimit);
  43. }
  44. });
  45. file.on('data', dataHandler);
  46. file.on('end', () => {
  47. // Add file instance to the req.files
  48. req.files = buildFields(req.files, fieldname, fileFactory(
  49. {
  50. buffer: complete(),
  51. name: parseFileName(options, filename),
  52. tempFilePath: getFilePath(),
  53. size: getFileSize(),
  54. hash: getHash(),
  55. encoding,
  56. truncated: file.truncated,
  57. mimetype: mime
  58. },
  59. options
  60. ));
  61. });
  62. file.on('error', cleanup, next);
  63. });
  64. busboy.on('finish', () => {
  65. if (options.parseNested) {
  66. req.body = processNested(req.body);
  67. req.files = processNested(req.files);
  68. }
  69. next();
  70. });
  71. busboy.on('error', next);
  72. req.pipe(busboy);
  73. };