Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
multer
✓ import multer from 'multer';
✗ const multer = require('multer');
The default export is the main Multer function used to configure and create middleware instances. While `require()` is prevalent in older Express.js examples and CJS environments, ESM `import` is recommended for modern Node.js projects.
multer.diskStorage
✓ import multer from 'multer'; const storage = multer.diskStorage({...});
✗ import { DiskStorage } from 'multer'; const storage = new DiskStorage({...});
Use the `multer.diskStorage()` factory method to create a storage engine for saving uploaded files to disk. It provides callbacks for customizing destination and filename. Do not attempt to import `DiskStorage` directly as a named export.
multer.memoryStorage
✓ import multer from 'multer'; const storage = multer.memoryStorage();
✗ import { MemoryStorage } from 'multer'; const storage = new MemoryStorage();
Use the `multer.memoryStorage()` factory method to store uploaded files in memory as `Buffer` objects. This is suitable for smaller files or temporary processing but should be used with caution for large files to avoid memory exhaustion. Do not attempt to import `MemoryStorage` directly as a named export.
Demonstrates basic file upload handling for single files, multiple files (up to 5), and text-only multipart forms using Multer middleware with Express.js, configuring disk storage with dynamic filenames.
import express from 'express';
import multer from 'multer';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import fs from 'fs';
// ESM equivalent of __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
const port = 3000;
const uploadDir = path.join(__dirname, 'uploads');
// Ensure the uploads directory exists
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}
// Configure disk storage
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, uploadDir);
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const upload = multer({ storage: storage });
// Serve a basic HTML form for upload
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head><title>Multer Upload</title></head>
<body>
<h2>Upload a Single File</h2>
<form action="/profile-upload" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
<button type="submit">Upload Avatar</button>
</form>
<hr>
<h2>Upload Multiple Files (max 5)</h2>
<form action="/gallery-upload" method="post" enctype="multipart/form-data">
<input type="file" name="photos" multiple />
<button type="submit">Upload Gallery</button>
</form>
<hr>
<h2>Text-Only Form</h2>
<form action="/text-data" method="post" enctype="multipart/form-data">
<input type="text" name="username" placeholder="Username" />
<button type="submit">Submit Text</button>
</form>
</body>
</html>
`);
});
// Handle single file upload
app.post('/profile-upload', upload.single('avatar'), (req, res) => {
if (req.file) {
console.log('Uploaded avatar:', req.file);
res.send(`File uploaded successfully: ${req.file.originalname} saved to ${req.file.path}`);
} else {
res.status(400).send('No file uploaded.');
}
});
// Handle multiple file upload
app.post('/gallery-upload', upload.array('photos', 5), (req, res) => {
if (req.files && req.files.length > 0) {
console.log('Uploaded photos:', req.files);
res.send(`${req.files.length} files uploaded successfully.`);
} else {
res.status(400).send('No files uploaded.');
}
});
// Handle text-only multipart form
app.post('/text-data', upload.none(), (req, res) => {
console.log('Received text data:', req.body);
res.send(`Text data received: ${JSON.stringify(req.body)}`);
});
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
console.log(`Uploads will be saved to: ${uploadDir}`);
});
Errors
Common errors & fixes
MulterError: Unexpected field
The field name provided in the HTML form's `<input type="file" name="...">` does not match the field name configured in Multer's middleware (e.g., `upload.single('avatar')` expects `name="avatar"`).
fixEnsure the `name` attribute of your file input in the HTML form exactly matches the string passed to Multer methods like `upload.single()`, `upload.array()`, or the `name` property in `upload.fields()`.
req.file or req.files is undefined (no file uploaded)
This typically occurs when the HTML form is missing `enctype="multipart/form-data"`, the `destination` directory for disk storage is not writable or does not exist, or the Multer middleware is not correctly applied to the route.
fixVerify that your HTML form has `enctype="multipart/form-data"`. Check that the `destination` path for `multer.diskStorage` exists and is writable by the Node.js process. Ensure Multer middleware (e.g., `upload.single()`) is correctly placed before your route handler.
Error: EBUSY: resource busy or locked, open '...' (for disk storage)
This can happen if the destination directory for file uploads is being accessed or locked by another process, or if the Multer stream is not properly drained/closed in older versions or specific error handling scenarios.
fixEnsure the `destination` directory is accessible and not locked. For robust error handling, especially in earlier Multer versions, ensure all streams are properly handled or closed. Upgrading to the latest Multer version (v2.1.1+) includes fixes for error/abort handling that might mitigate some stream-related issues.
Error: Multipart: Boundary not found
This error typically indicates that the incoming request is not a valid `multipart/form-data` request, often due to incorrect client-side configuration, corrupted data, or a proxy/load balancer modifying the request.
fixVerify that your client-side code (HTML form or API request) correctly sets `Content-Type: multipart/form-data` and constructs the body according to the multipart specification. If using proxies, ensure they are not interfering with the request body.
Audit
Dependencies
busboyrequiredMulter is built on top of `busboy` for efficient parsing of `multipart/form-data` requests.
expressoptionalMulter is designed as an Express.js middleware and is predominantly used within Express applications.