or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Express File Upload

Express File Upload is a simple Express.js middleware that provides file upload functionality by wrapping around the Busboy library. It automatically parses multipart forms and makes uploaded files available through the req.files object with a clean, intuitive API.

Package Information

  • Package Name: express-fileupload
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install express-fileupload

Core Imports

const fileUpload = require('express-fileupload');

ESM:

import fileUpload from 'express-fileupload';

Basic Usage

const express = require('express');
const fileUpload = require('express-fileupload');

const app = express();

// Default options
app.use(fileUpload());

app.post('/upload', (req, res) => {
  if (!req.files || Object.keys(req.files).length === 0) {
    return res.status(400).send('No files were uploaded.');
  }

  // The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
  let sampleFile = req.files.sampleFile;

  // Use the mv method to move the file to your desired upload directory
  sampleFile.mv('/path/to/upload/directory/filename.jpg', (err) => {
    if (err) return res.status(500).send(err);
    res.send('File uploaded!');
  });
});

Architecture

Express File Upload is built around several key components:

  • Middleware Factory: The main export creates Express middleware with customizable options
  • Multipart Processing: Uses Busboy internally to parse multipart/form-data requests
  • File Handling: Supports both memory-based and temporary file-based upload handling
  • File Objects: Each uploaded file becomes an object with properties and methods for easy manipulation
  • Configuration System: Extensive options for controlling upload behavior, limits, and file handling

Capabilities

Middleware Factory Function

Creates Express middleware for handling file uploads with extensive configuration options.

/**
 * Creates Express middleware for handling file uploads
 * @param {Object} options - Configuration options for file upload behavior
 * @returns {Function} Express middleware function (req, res, next) => void
 */
function fileUpload(options);

Usage Examples:

// Basic usage with default options
app.use(fileUpload());

// With custom options
app.use(fileUpload({
  limits: { fileSize: 50 * 1024 * 1024 }, // 50MB limit
  useTempFiles: true,
  tempFileDir: '/tmp/',
  debug: true
}));

// With advanced configuration
app.use(fileUpload({
  createParentPath: true,
  safeFileNames: true,
  preserveExtension: 4,
  abortOnLimit: true,
  responseOnLimit: 'File size limit has been reached',
  uploadTimeout: 120000, // 2 minutes
  hashAlgorithm: 'sha256'
}));

File Upload Options

Comprehensive configuration options for controlling upload behavior.

interface FileUploadOptions {
  /** Enable debug logging */
  debug?: boolean;
  /** Custom logger with .log() method */
  logger?: Object;
  /** Upload timeout in milliseconds */
  uploadTimeout?: number;
  /** Custom file handler function */
  fileHandler?: boolean | Function;
  /** Decode URI-encoded filenames */
  uriDecodeFileNames?: boolean;
  /** Sanitize unsafe characters in filenames */
  safeFileNames?: boolean | RegExp;
  /** Preserve file extensions during sanitization */
  preserveExtension?: boolean | number;
  /** Abort upload when size limit reached */
  abortOnLimit?: boolean;
  /** Response message for size limit violations */
  responseOnLimit?: string;
  /** Custom limit handler function */
  limitHandler?: Function;
  /** Create parent directories if they don't exist */
  createParentPath?: boolean;
  /** Parse nested form fields */
  parseNested?: boolean;
  /** Use temporary files instead of memory */
  useTempFiles?: boolean;
  /** Directory for temporary files */
  tempFileDir?: string;
  /** File permissions for temporary files */
  tempFilePermissions?: number;
  /** Hash algorithm for file checksums */
  hashAlgorithm?: string;
}

Default Values:

  • debug: false
  • logger: console
  • uploadTimeout: 60000 (60 seconds)
  • fileHandler: false
  • uriDecodeFileNames: false
  • safeFileNames: false
  • preserveExtension: false
  • abortOnLimit: false
  • responseOnLimit: 'File size limit has been reached'
  • limitHandler: false
  • createParentPath: false
  • parseNested: false
  • useTempFiles: false
  • tempFileDir: 'tmp' (relative to current working directory)
  • tempFilePermissions: 0o644
  • hashAlgorithm: 'md5'

File Object API

Each uploaded file becomes an object with properties and methods for file manipulation.

interface UploadedFile {
  /** Original filename */
  name: string;
  /** File content as Buffer (empty if useTempFiles is true) */
  data: Buffer;
  /** File size in bytes */
  size: number;
  /** File encoding */
  encoding: string;
  /** Path to temporary file (if useTempFiles is true) */
  tempFilePath: string;
  /** Whether file was truncated due to size limits */
  truncated: boolean;
  /** MIME type of the file */
  mimetype: string;
  /** File checksum using configured hash algorithm */
  md5: string;
  
  /**
   * Move file to specified location
   * @param {string} filePath - Destination file path
   * @param {Function} callback - Optional callback function
   * @returns {Promise|undefined} Promise if no callback provided
   */
  mv(filePath: string, callback?: Function): Promise<void> | undefined;
}

Usage Examples:

app.post('/upload', (req, res) => {
  const uploadedFile = req.files.myFile;
  
  // Access file properties
  console.log('Filename:', uploadedFile.name);
  console.log('Size:', uploadedFile.size);
  console.log('MIME type:', uploadedFile.mimetype);
  console.log('MD5 checksum:', uploadedFile.md5);
  
  // Move file using callback
  uploadedFile.mv('/uploads/' + uploadedFile.name, (err) => {
    if (err) return res.status(500).send(err);
    res.send('File uploaded successfully');
  });
});

// Using Promise-based approach
app.post('/upload-async', async (req, res) => {
  try {
    const uploadedFile = req.files.myFile;
    await uploadedFile.mv('/uploads/' + uploadedFile.name);
    res.send('File uploaded successfully');
  } catch (err) {
    res.status(500).send(err);
  }
});

Request Integration

The middleware automatically adds file objects to the Express request object.

interface Request {
  /** 
   * Object containing uploaded files, where keys are form field names 
   * and values are UploadedFile objects or arrays of UploadedFile objects
   */
  files: { [fieldName: string]: UploadedFile | UploadedFile[] } | null;
}

Usage Examples:

app.post('/single-upload', (req, res) => {
  // Single file upload
  const file = req.files.singleFile;
  // file is an UploadedFile object
});

app.post('/multi-upload', (req, res) => {
  // Multiple files with same field name
  const files = req.files.multipleFiles;
  if (Array.isArray(files)) {
    // files is an array of UploadedFile objects
    files.forEach(file => {
      console.log(file.name);
    });
  } else {
    // Single file (files is an UploadedFile object)
    console.log(files.name);
  }
});

app.post('/mixed-upload', (req, res) => {
  // Mixed upload with different field names
  const profilePic = req.files.profilePicture;
  const documents = req.files.documents; // Could be single file or array
  const avatar = req.files.avatar;
});

Busboy Integration

All Busboy configuration options can be passed through the options object for advanced multipart parsing control.

interface BusboyOptions {
  /** Field name size limit */
  fieldNameSize?: number;
  /** Field value size limit */
  fieldSize?: number;
  /** Number of non-file fields limit */
  fields?: number;
  /** File size limit per file */
  fileSize?: number;
  /** Number of files limit */
  files?: number;
  /** Number of parts limit */
  parts?: number;
  /** Header pairs limit */
  headerPairs?: number;
}

Usage Examples:

// Combine express-fileupload options with Busboy options
app.use(fileUpload({
  // Express-fileupload options
  useTempFiles: true,
  tempFileDir: '/tmp/',
  createParentPath: true,
  
  // Busboy options
  limits: {
    fileSize: 10 * 1024 * 1024, // 10MB per file
    files: 5, // Maximum 5 files
    fieldSize: 1024, // 1KB per field
    fields: 10 // Maximum 10 non-file fields
  }
}));

Error Handling

The middleware integrates with Express error handling and can generate errors for various conditions:

  • Invalid hash algorithms: When specified hashAlgorithm is not supported by the system
  • Invalid file permissions: When tempFilePermissions are outside acceptable range (0o600-0o777)
  • Upload timeouts: When files take longer than uploadTimeout to upload
  • File system errors: During file operations when using temporary files
  • Size limit violations: When abortOnLimit is true and limits are exceeded
// Error handling example
app.use(fileUpload({
  uploadTimeout: 60000,
  abortOnLimit: true,
  limits: { fileSize: 1024 * 1024 } // 1MB
}));

app.use((err, req, res, next) => {
  console.error('File upload error:', err);
  res.status(500).send('Upload failed');
});

Common Patterns

Temporary Files vs Memory

// Memory-based (default) - good for small files
app.use(fileUpload()); // Files stored in req.files[].data Buffer

// Temporary files - better for large files
app.use(fileUpload({
  useTempFiles: true,
  tempFileDir: '/tmp/'
})); // Files stored on disk, accessible via req.files[].tempFilePath

File Validation and Processing

app.post('/upload', (req, res) => {
  if (!req.files || !req.files.document) {
    return res.status(400).send('No file uploaded');
  }
  
  const file = req.files.document;
  
  // Validate file type
  if (!file.mimetype.startsWith('image/')) {
    return res.status(400).send('Only images allowed');
  }
  
  // Validate file size (additional check)
  if (file.size > 5 * 1024 * 1024) {
    return res.status(400).send('File too large');
  }
  
  // Process file
  const filename = Date.now() + '_' + file.name;
  file.mv('./uploads/' + filename, (err) => {
    if (err) return res.status(500).send(err);
    res.json({ message: 'Success', filename: filename });
  });
});

Safe File Naming

app.use(fileUpload({
  safeFileNames: true,      // Remove dangerous characters
  preserveExtension: 4,     // Keep up to 4-char extensions
  uriDecodeFileNames: true  // Decode URI-encoded names
}));