busboy vs express-fileupload vs form-data vs formidable vs multer
File Upload Middleware for Node.js
busboyexpress-fileuploadform-dataformidablemulterSimilar Packages:

File Upload Middleware for Node.js

These npm packages are designed to handle file uploads in Node.js applications. They provide various functionalities for parsing incoming multipart/form-data requests, which is essential for handling file uploads from clients. Each package has its own strengths and weaknesses, making them suitable for different scenarios based on project requirements, performance needs, and ease of use. Understanding these differences is crucial for selecting the right package for your application.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
busboy03,000124 kB37--
express-fileupload01,560119 kB249 months agoMIT
form-data02,35581.2 kB1375 months agoMIT
formidable0-204 kB-a year agoMIT
multer012,03631.5 kB252a month agoMIT

Feature Comparison: busboy vs express-fileupload vs form-data vs formidable vs multer

Ease of Use

  • busboy:

    Busboy is a low-level streaming parser that requires more setup and understanding of streams. It may not be the best choice for beginners or those looking for a quick implementation.

  • express-fileupload:

    Express-fileupload is designed for simplicity and ease of use, making it ideal for developers who want to quickly implement file uploads without extensive configuration.

  • form-data:

    Form-data is primarily used for sending files to external services rather than handling uploads, so it does not provide an easy interface for incoming file uploads.

  • formidable:

    Formidable offers a straightforward API for handling file uploads, but it may require a bit more configuration compared to express-fileupload.

  • multer:

    Multer is easy to set up and integrates seamlessly with Express.js, providing a user-friendly experience for handling file uploads.

Performance

  • busboy:

    Busboy is highly performant due to its streaming nature, allowing for efficient handling of large files without consuming excessive memory.

  • express-fileupload:

    Express-fileupload is suitable for small to medium files, but may not perform as well as Busboy for larger uploads due to its in-memory processing.

  • form-data:

    Form-data is not used for handling incoming uploads, so performance considerations are more relevant when sending files to external services.

  • formidable:

    Formidable performs well for moderate file sizes but can become slower with very large files due to its processing model.

  • multer:

    Multer is efficient for handling file uploads, especially when configured with disk storage, but may require optimization for very large files.

File Size Limitations

  • busboy:

    Busboy allows you to set file size limits easily, making it suitable for applications that need to enforce strict upload limits.

  • express-fileupload:

    Express-fileupload also supports file size limits, but it may not be as flexible as Busboy in terms of configuration.

  • form-data:

    Form-data does not impose file size limits as it is used for sending files, not receiving them.

  • formidable:

    Formidable allows you to set file size limits and provides feedback on upload progress, making it a good choice for applications that need to manage large uploads.

  • multer:

    Multer allows you to set file size limits and provides options for handling errors when limits are exceeded.

Streaming Support

  • busboy:

    Busboy excels in streaming file uploads, allowing files to be processed as they are received, which is ideal for large files.

  • express-fileupload:

    Express-fileupload does not support streaming; it buffers the entire file in memory before processing, which may lead to performance issues with large files.

  • form-data:

    Form-data is designed for constructing requests, not for streaming uploads, so it lacks this feature.

  • formidable:

    Formidable supports streaming uploads, allowing for efficient processing of files as they are received, similar to Busboy.

  • multer:

    Multer does not support streaming in the same way as Busboy, as it buffers files in memory or on disk before processing.

Integration with Express

  • busboy:

    Busboy can be integrated with Express, but it requires more manual setup compared to other packages.

  • express-fileupload:

    Express-fileupload is specifically designed for Express, making it the easiest to integrate with minimal configuration.

  • form-data:

    Form-data is not designed for Express integration, as it is used for sending requests rather than handling them.

  • formidable:

    Formidable can be integrated with Express, but it requires additional setup compared to express-fileupload.

  • multer:

    Multer is built for Express and provides a straightforward middleware approach, making it very easy to use in Express applications.

How to Choose: busboy vs express-fileupload vs form-data vs formidable vs multer

  • busboy:

    Choose Busboy if you need a lightweight and efficient solution for handling file uploads with a focus on performance. It streams the files directly to the filesystem or memory, which is ideal for applications that require high throughput and low memory usage.

  • express-fileupload:

    Select express-fileupload for a simple and easy-to-use middleware that integrates seamlessly with Express.js. It is suitable for small to medium-sized applications where ease of setup and use is prioritized over advanced features.

  • form-data:

    Use form-data if you need to construct and send multipart/form-data requests from Node.js. It is particularly useful for scenarios where you need to upload files to an external API or service, rather than handling incoming uploads.

  • formidable:

    Opt for Formidable if you require robust parsing capabilities and support for file uploads. It handles file uploads well and provides a rich set of features, including progress events and file size limits, making it suitable for more complex applications.

  • multer:

    Choose Multer if you are looking for a middleware that integrates directly with Express.js and provides a simple way to handle file uploads. It offers various storage options and is particularly useful for applications that need to manage uploaded files efficiently.

README for busboy

Description

A node.js module for parsing incoming HTML form data.

Changes (breaking or otherwise) in v1.0.0 can be found here.

Requirements

Install

npm install busboy

Examples

  • Parsing (multipart) with default options:
const http = require('http');

const busboy = require('busboy');

http.createServer((req, res) => {
  if (req.method === 'POST') {
    console.log('POST request');
    const bb = busboy({ headers: req.headers });
    bb.on('file', (name, file, info) => {
      const { filename, encoding, mimeType } = info;
      console.log(
        `File [${name}]: filename: %j, encoding: %j, mimeType: %j`,
        filename,
        encoding,
        mimeType
      );
      file.on('data', (data) => {
        console.log(`File [${name}] got ${data.length} bytes`);
      }).on('close', () => {
        console.log(`File [${name}] done`);
      });
    });
    bb.on('field', (name, val, info) => {
      console.log(`Field [${name}]: value: %j`, val);
    });
    bb.on('close', () => {
      console.log('Done parsing form!');
      res.writeHead(303, { Connection: 'close', Location: '/' });
      res.end();
    });
    req.pipe(bb);
  } else if (req.method === 'GET') {
    res.writeHead(200, { Connection: 'close' });
    res.end(`
      <html>
        <head></head>
        <body>
          <form method="POST" enctype="multipart/form-data">
            <input type="file" name="filefield"><br />
            <input type="text" name="textfield"><br />
            <input type="submit">
          </form>
        </body>
      </html>
    `);
  }
}).listen(8000, () => {
  console.log('Listening for requests');
});

// Example output:
//
// Listening for requests
//   < ... form submitted ... >
// POST request
// File [filefield]: filename: "logo.jpg", encoding: "binary", mime: "image/jpeg"
// File [filefield] got 11912 bytes
// Field [textfield]: value: "testing! :-)"
// File [filefield] done
// Done parsing form!
  • Save all incoming files to disk:
const { randomFillSync } = require('crypto');
const fs = require('fs');
const http = require('http');
const os = require('os');
const path = require('path');

const busboy = require('busboy');

const random = (() => {
  const buf = Buffer.alloc(16);
  return () => randomFillSync(buf).toString('hex');
})();

http.createServer((req, res) => {
  if (req.method === 'POST') {
    const bb = busboy({ headers: req.headers });
    bb.on('file', (name, file, info) => {
      const saveTo = path.join(os.tmpdir(), `busboy-upload-${random()}`);
      file.pipe(fs.createWriteStream(saveTo));
    });
    bb.on('close', () => {
      res.writeHead(200, { 'Connection': 'close' });
      res.end(`That's all folks!`);
    });
    req.pipe(bb);
    return;
  }
  res.writeHead(404);
  res.end();
}).listen(8000, () => {
  console.log('Listening for requests');
});

API

Exports

busboy exports a single function:

( function )(< object >config) - Creates and returns a new Writable form parser stream.

  • Valid config properties:

    • headers - object - These are the HTTP headers of the incoming request, which are used by individual parsers.

    • highWaterMark - integer - highWaterMark to use for the parser stream. Default: node's stream.Writable default.

    • fileHwm - integer - highWaterMark to use for individual file streams. Default: node's stream.Readable default.

    • defCharset - string - Default character set to use when one isn't defined. Default: 'utf8'.

    • defParamCharset - string - For multipart forms, the default character set to use for values of part header parameters (e.g. filename) that are not extended parameters (that contain an explicit charset). Default: 'latin1'.

    • preservePath - boolean - If paths in filenames from file parts in a 'multipart/form-data' request shall be preserved. Default: false.

    • limits - object - Various limits on incoming data. Valid properties are:

      • fieldNameSize - integer - Max field name size (in bytes). Default: 100.

      • fieldSize - integer - Max field value size (in bytes). Default: 1048576 (1MB).

      • fields - integer - Max number of non-file fields. Default: Infinity.

      • fileSize - integer - For multipart forms, the max file size (in bytes). Default: Infinity.

      • files - integer - For multipart forms, the max number of file fields. Default: Infinity.

      • parts - integer - For multipart forms, the max number of parts (fields + files). Default: Infinity.

      • headerPairs - integer - For multipart forms, the max number of header key-value pairs to parse. Default: 2000 (same as node's http module).

This function can throw exceptions if there is something wrong with the values in config. For example, if the Content-Type in headers is missing entirely, is not a supported type, or is missing the boundary for 'multipart/form-data' requests.

(Special) Parser stream events

  • file(< string >name, < Readable >stream, < object >info) - Emitted for each new file found. name contains the form field name. stream is a Readable stream containing the file's data. No transformations/conversions (e.g. base64 to raw binary) are done on the file's data. info contains the following properties:

    • filename - string - If supplied, this contains the file's filename. WARNING: You should almost never use this value as-is (especially if you are using preservePath: true in your config) as it could contain malicious input. You are better off generating your own (safe) filenames, or at the very least using a hash of the filename.

    • encoding - string - The file's 'Content-Transfer-Encoding' value.

    • mimeType - string - The file's 'Content-Type' value.

    Note: If you listen for this event, you should always consume the stream whether you care about its contents or not (you can simply do stream.resume(); if you want to discard/skip the contents), otherwise the 'finish'/'close' event will never fire on the busboy parser stream. However, if you aren't accepting files, you can either simply not listen for the 'file' event at all or set limits.files to 0, and any/all files will be automatically skipped (these skipped files will still count towards any configured limits.files and limits.parts limits though).

    Note: If a configured limits.fileSize limit was reached for a file, stream will both have a boolean property truncated set to true (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens.

  • field(< string >name, < string >value, < object >info) - Emitted for each new non-file field found. name contains the form field name. value contains the string value of the field. info contains the following properties:

    • nameTruncated - boolean - Whether name was truncated or not (due to a configured limits.fieldNameSize limit)

    • valueTruncated - boolean - Whether value was truncated or not (due to a configured limits.fieldSize limit)

    • encoding - string - The field's 'Content-Transfer-Encoding' value.

    • mimeType - string - The field's 'Content-Type' value.

  • partsLimit() - Emitted when the configured limits.parts limit has been reached. No more 'file' or 'field' events will be emitted.

  • filesLimit() - Emitted when the configured limits.files limit has been reached. No more 'file' events will be emitted.

  • fieldsLimit() - Emitted when the configured limits.fields limit has been reached. No more 'field' events will be emitted.