CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-multiparty

multipart/form-data parser which supports streaming

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

multiparty

multiparty is a Node.js library for parsing HTTP requests with content-type multipart/form-data, specifically designed for handling file uploads with streaming support. It provides a comprehensive API for processing form data without loading entire files into memory, making it ideal for efficient file upload handling in web applications.

Package Information

  • Package Name: multiparty
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install multiparty

Core Imports

const multiparty = require('multiparty');

For ES modules:

import * as multiparty from 'multiparty';

Basic Usage

const multiparty = require('multiparty');
const http = require('http');

http.createServer(function(req, res) {
  if (req.url === '/upload' && req.method === 'POST') {
    // Parse a file upload with callback
    const form = new multiparty.Form();
    
    form.parse(req, function(err, fields, files) {
      if (err) {
        res.writeHead(400, { 'content-type': 'text/plain' });
        res.end('Error: ' + err.message);
        return;
      }
      
      res.writeHead(200, { 'content-type': 'application/json' });
      res.end(JSON.stringify({ fields, files }));
    });
  }
}).listen(8080);

Architecture

multiparty is built around several key concepts:

  • Form Class: Main parser that extends Node.js Writable stream for processing multipart data
  • Event-driven Architecture: Emits events for different parts of the parsing process (parts, fields, files, errors)
  • Streaming Support: Handles large file uploads without loading entire files into memory
  • Automatic Mode Detection: Switches between part/field/file events based on listeners attached
  • Configuration Options: Extensive options for controlling parsing behavior, limits, and file handling

Capabilities

Form Constructor

Creates a new multipart form parser with optional configuration.

/**
 * Creates a new multipart form parser
 * @param {Object} options - Configuration options
 */
function Form(options);

interface FormOptions {
  /** Encoding for incoming form fields (default: 'utf8') */
  encoding?: string;
  /** Maximum memory for all fields in bytes (default: 2MB) */
  maxFieldsSize?: number;
  /** Maximum number of fields to parse (default: 1000) */
  maxFields?: number;
  /** Maximum total bytes for all files (default: Infinity) */
  maxFilesSize?: number;
  /** Enable automatic field event emission (default: false) */
  autoFields?: boolean;
  /** Enable automatic file event emission (default: false) */
  autoFiles?: boolean;
  /** Directory for temporary file uploads (default: os.tmpdir()) */
  uploadDir?: string;
}

Form Parsing

Parses an incoming HTTP request containing multipart form data.

/**
 * Parse an HTTP request with multipart form data
 * @param {IncomingMessage} request - Node.js HTTP request object
 * @param {Function} [callback] - Optional callback for simplified usage
 */
form.parse(request, callback);

/**
 * Callback function signature when provided
 * @param {Error|null} err - Error if parsing failed
 * @param {Object} fields - Object with field names as keys, arrays of values as values
 * @param {Object} files - Object with field names as keys, arrays of file objects as values
 */
function parseCallback(err, fields, files);

Form Properties

Access current parsing state and progress information.

/** Current number of bytes received */
form.bytesReceived: number;

/** Expected total bytes from Content-Length header */
form.bytesExpected: number | null;

/** Current error state of the parser */
form.error: Error | null;

/** Array of currently opened file handles */
form.openedFiles: Array;

/** Total size of all parsed field data */
form.totalFieldSize: number;

/** Total count of parsed fields */
form.totalFieldCount: number;

/** Total size of all parsed file data */
form.totalFileSize: number;

Event Handling

multiparty uses an event-driven architecture for handling different stages of form parsing.

/**
 * Error event - emitted when parsing encounters an error
 * @param {Error} err - Error object with optional statusCode property
 */
form.on('error', function(err));

/**
 * Part event - emitted for each part in the multipart data
 * @param {ReadableStream} part - Stream for the part data
 */
form.on('part', function(part));

/**
 * Field event - emitted for each form field (requires autoFields)
 * @param {string} name - Field name
 * @param {string} value - Field value
 */
form.on('field', function(name, value));

/**
 * File event - emitted for each file upload (requires autoFiles)
 * @param {string} name - Field name for the file
 * @param {Object} file - File object with metadata
 */
form.on('file', function(name, file));

/**
 * Progress event - emitted during parsing for progress tracking
 * @param {number} bytesReceived - Total bytes received so far
 * @param {number|null} bytesExpected - Expected total bytes
 */
form.on('progress', function(bytesReceived, bytesExpected));

/**
 * Close event - emitted when parsing completes successfully
 */
form.on('close', function());

/**
 * Aborted event - emitted when request is aborted
 */
form.on('aborted', function());

Part Stream Properties

When handling part events, the part stream has additional properties for metadata.

interface PartStream extends ReadableStream {
  /** HTTP headers for this part */
  headers: Object;
  /** Field name for this part */
  name: string;
  /** Filename if this part is a file upload */
  filename?: string;
  /** Byte offset of this part in the request body */
  byteOffset: number;
  /** Size of this part in bytes (if known) */
  byteCount?: number;
}

File Object Structure

When using autoFiles mode or the parse callback, files are represented as objects with metadata.

interface FileObject {
  /** Field name for this file */
  fieldName: string;
  /** Original filename as reported by the client */
  originalFilename: string;
  /** Absolute path where the file was saved on disk */
  path: string;
  /** HTTP headers sent with this file */
  headers: Object;
  /** Size of the uploaded file in bytes */
  size: number;
}

Usage Examples

Event-based Processing

const form = new multiparty.Form({
  uploadDir: './uploads',
  maxFilesSize: 50 * 1024 * 1024 // 50MB limit
});

form.on('error', function(err) {
  console.error('Parsing error:', err.message);
  if (err.statusCode) {
    res.writeHead(err.statusCode);
  }
  res.end('Upload failed: ' + err.message);
});

form.on('part', function(part) {
  console.log('Received part:', part.name);
  if (part.filename) {
    console.log('File upload:', part.filename);
    // Handle file part
    part.on('data', function(chunk) {
      // Process file chunk
    });
  } else {
    console.log('Form field:', part.name);
    // Handle field part
    part.resume(); // Skip field data
  }
});

form.on('close', function() {
  console.log('Upload completed successfully');
  res.writeHead(200);
  res.end('Upload complete');
});

form.parse(req);

Automatic File Handling

const form = new multiparty.Form({
  uploadDir: './uploads',
  maxFilesSize: 100 * 1024 * 1024, // 100MB total
  maxFieldsSize: 2 * 1024 * 1024    // 2MB for fields
});

form.on('file', function(name, file) {
  console.log('File uploaded:', {
    field: name,
    filename: file.originalFilename,
    path: file.path,
    size: file.size
  });
  
  // File is automatically saved to disk at file.path
  // You can now move it to a permanent location
});

form.on('field', function(name, value) {
  console.log('Field received:', name, '=', value);
});

form.parse(req);

Progress Tracking

const form = new multiparty.Form();

form.on('progress', function(bytesReceived, bytesExpected) {
  if (bytesExpected) {
    const percent = Math.round((bytesReceived / bytesExpected) * 100);
    console.log(`Upload progress: ${percent}% (${bytesReceived} / ${bytesExpected} bytes)`);
  } else {
    console.log(`Upload progress: ${bytesReceived} bytes received`);
  }
});

form.parse(req);

Error Handling

multiparty provides detailed error handling with HTTP status codes for common scenarios:

  • 400 Bad Request: Malformed multipart data, missing boundary, encoding issues
  • 413 Payload Too Large: Field size, file size, or field count limits exceeded
  • 415 Unsupported Media Type: Invalid or missing Content-Type header
form.on('error', function(err) {
  console.error('Parse error:', err.message);
  
  // Check for specific error conditions
  if (err.statusCode === 413) {
    console.log('Upload too large');
  } else if (err.statusCode === 400) {
    console.log('Malformed request');
  }
  
  // Send appropriate HTTP response
  res.writeHead(err.statusCode || 500);
  res.end(err.message);
});

Configuration Recommendations

Production Settings

const form = new multiparty.Form({
  encoding: 'utf8',
  maxFieldsSize: 2 * 1024 * 1024,    // 2MB for form fields
  maxFields: 100,                     // Limit number of fields
  maxFilesSize: 50 * 1024 * 1024,     // 50MB total for files
  uploadDir: '/tmp/uploads'           // Dedicated upload directory
});

Development Settings

const form = new multiparty.Form({
  encoding: 'utf8',
  maxFieldsSize: 10 * 1024 * 1024,   // 10MB for testing
  maxFields: 1000,                    // Default
  maxFilesSize: 100 * 1024 * 1024,   // 100MB for testing
  uploadDir: './dev-uploads'          // Local development directory
});
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/multiparty@4.2.x
Publish Source
CLI
Badge
tessl/npm-multiparty badge