Multer для JavaScript (Node.js): полное руководство с примерами
1. Что это и зачем нужна
Multer — это популярная middleware-библиотека для Node.js, предназначенная для обработки multipart/form-data — формата, который используется при загрузке файлов через HTML-формы. В отличие от стандартного модуля body-parser, который работает только с JSON и URL-кодированными данными, Multer умеет разбирать составные запросы, извлекать из них файлы и сохранять их на сервере (в память или на диск). Библиотека написана поверх модуля busboy и предоставляет удобный API для настройки путей, имён файлов, фильтрации типов и ограничения размера.
Зачем нужна Multer? В любом веб-приложении, где пользователь может загрузить аватар, документ, изображение или видео, необходимо обработать multipart/form-data. Express.js (самый популярный фреймворк для Node.js) не имеет встроенной поддержки этого формата, поэтому Multer становится обязательным инструментом. Она позволяет разработчику сосредоточиться на бизнес-логике, а не на низкоуровневом парсинге бинарных данных.
Multer поддерживает загрузку одного или нескольких файлов одновременно, работу с полями формы, кастомную генерацию имён файлов, фильтрацию по MIME-типам и расширениям, а также ограничение размера загружаемых данных. Благодаря гибкой конфигурации, библиотека подходит как для простых проектов (например, загрузка аватарок), так и для сложных систем с облачным хранением (через пользовательские хранилища).
2. Установка
Установка производится через npm (Node Package Manager). Убедитесь, что у вас установлен Node.js (версия 12 или выше).
npm install multer
После установки библиотека будет доступна для импорта в ваш проект.
3. Быстрый старт — минимальный рабочий пример
Создадим простой сервер на Express.js, который принимает загрузку одного файла через форму и сохраняет его в папку uploads/.
Шаг 1. Структура проекта
mkdir multer-example
cd multer-example
npm init -y
npm install express multer
touch index.html
touch server.js
Шаг 2. HTML-форма (index.html)
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Загрузка файла</title>
</head>
<body>
<h1>Загрузите файл</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="myFile" required>
<button type="submit">Отправить</button>
</form>
</body>
</html>
Шаг 3. Сервер (server.js)
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const PORT = 3000;
// Настройка Multer: файлы будут сохраняться в папку 'uploads/'
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
// Генерируем уникальное имя: текущая дата + оригинальное расширение
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, uniqueSuffix + path.extname(file.originalname));
}
});
const upload = multer({ storage: storage });
// Раздача статического HTML
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// Обработка загрузки файла
app.post('/upload', upload.single('myFile'), (req, res) => {
if (!req.file) {
return res.status(400).send('Файл не загружен.');
}
res.send(`Файл "${req.file.originalname}" успешно загружен. Размер: ${req.file.size} байт.`);
});
app.listen(PORT, () => {
console.log(`Сервер запущен на http://localhost:${PORT}`);
});
Шаг 4. Запуск
node server.js
Откройте браузер по адресу http://localhost:3000, выберите файл и нажмите "Отправить". Файл сохранится в папку uploads/.
4. Основные методы/функции/классы
4.1. multer(options)
Сигнатура: multer(options?: MulterOptions): Multer
Что делает: Создаёт экземпляр middleware Multer с заданной конфигурацией. Основные опции: storage (место хранения), limits (ограничения), fileFilter (фильтр файлов).
const upload = multer({
dest: 'uploads/', // Простейший вариант — сохранение в папку
limits: { fileSize: 5 * 1024 * 1024 } // Ограничение 5 МБ
});
4.2. upload.single(fieldname)
Сигнатура: upload.single(fieldname: string): Middleware
Что делает: Обрабатывает загрузку ровно одного файла из поля формы с именем fieldname. Файл будет доступен в req.file.
app.post('/upload-avatar', upload.single('avatar'), (req, res) => {
console.log(req.file); // { fieldname, originalname, encoding, mimetype, destination, filename, path, size }
res.json({ message: 'Аватар загружен' });
});
4.3. upload.array(fieldname, maxCount)
Сигнатура: upload.array(fieldname: string, maxCount?: number): Middleware
Что делает: Обрабатывает загрузку нескольких файлов из одного поля формы. Все файлы будут доступны в req.files (массив). Параметр maxCount ограничивает максимальное количество файлов.
app.post('/upload-gallery', upload.array('photos', 5), (req, res) => {
console.log(`Загружено ${req.files.length} файлов`);
res.json({ files: req.files.map(f => f.filename) });
});
4.4. upload.fields(fields)
Сигнатура: upload.fields(fields: FieldConfig[]): Middleware
Что делает: Обрабатывает загрузку файлов из нескольких разных полей формы. fields — массив объектов { name: string, maxCount?: number }. Файлы доступны в req.files как объект, где ключи — имена полей.
app.post('/upload-docs', upload.fields([
{ name: 'passport', maxCount: 1 },
{ name: 'photos', maxCount: 3 }
]), (req, res) => {
const passport = req.files['passport'][0];
const photos = req.files['photos'];
res.json({ passport: passport.filename, photos: photos.map(p => p.filename) });
});
4.5. upload.none()
Сигнатура: upload.none(): Middleware
Что делает: Обрабатывает запросы multipart/form-data, но не ожидает загрузки файлов. Используется, когда форма содержит только текстовые поля, но отправляется в этом формате (например, для совместимости).
app.post('/submit-form', upload.none(), (req, res) => {
console.log(req.body); // { name: 'John', email: 'john@example.com' }
res.json({ received: true });
});
4.6. multer.diskStorage(options)
Сигнатура: multer.diskStorage(options: DiskStorageOptions): StorageEngine
Что делает: Создаёт хранилище на диске. Позволяет настроить destination (папка назначения) и filename (имя файла). Это самый распространённый способ хранения.
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname);
}
});
const upload = multer({ storage: storage });
4.7. multer.memoryStorage()
Сигнатура: multer.memoryStorage(): StorageEngine
Что делает: Создаёт хранилище в оперативной памяти. Файл сохраняется как Buffer в req.file.buffer. Полезно для дальнейшей обработки (например, загрузка в облако) без записи на диск.
const upload = multer({ storage: multer.memoryStorage() });
app.post('/upload-to-cloud', upload.single('file'), (req, res) => {
const buffer = req.file.buffer;
// Отправляем buffer в S3, Firebase и т.д.
res.send('Файл загружен в память');
});
4.8. req.file и req.files
Сигнатура: Свойства объекта запроса (не функции, но ключевые для понимания)
Что делает: После обработки Multer, в объект req добавляются свойства file (для single) или files (для array/fields). Каждый файл содержит: fieldname, originalname, encoding, mimetype, destination, filename, path, size (для диска) или buffer (для памяти).
app.post('/info', upload.single('doc'), (req, res) => {
const file = req.file;
res.json({
originalName: file.originalname,
mimeType: file.mimetype,
sizeInBytes: file.size,
path: file.path
});
});
4.9. fileFilter (опция конфигурации)
Сигнатура: fileFilter: (req: Request, file: File, cb: Callback) => void
Что делает: Функция-фильтр, которая вызывается для каждого файла. Позволяет отклонить файл по MIME-типу, расширению или любым другим критериям. Вызов cb(null, true) принимает файл, cb(null, false) — отклоняет.
const upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true); // Принимаем
} else {
cb(new Error('Только JPEG и PNG разрешены'), false); // Отклоняем
}
}
});
4.10. limits (опция конфигурации)
Сигнатура: limits: { fieldNameSize?: number, fieldSize?: number, fields?: number, fileSize?: number, files?: number, parts?: number, headerPairs?: number }
Что делает: Объект, задающий ограничения на размеры и количество полей/файлов. Самый часто используемый — fileSize (максимальный размер файла в байтах).
const upload = multer({
storage: storage,
limits: {
fileSize: 2 * 1024 * 1024, // 2 MB
files: 5, // максимум 5 файлов
fields: 10 // максимум 10 текстовых полей
}
});
5. Реальный практический пример (100-200 строк кода)
Разработаем полноценный REST API для загрузки аватарок пользователей с валидацией, хранением на диске и возвратом URL. Также добавим обработку ошибок.
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const app = express();
const PORT = 3000;
// Создаём папку для аватарок, если её нет
const avatarDir = path.join(__dirname, 'avatars');
if (!fs.existsSync(avatarDir)) {
fs.mkdirSync(avatarDir, { recursive: true });
}
// Настройка хранилища
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, avatarDir);
},
filename: (req, file, cb) => {
// Генерируем имя: userId + timestamp + расширение
const userId = req.body.userId || 'anonymous';
const ext =