Multer для JavaScript (Node.js): полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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 =                    

Рекомендаций