Przesyłanie wieloczęściowe z interceptorami Multer
Skonfiguruj FileInterceptor i FilesInterceptor do obsługi przesyłania jednego lub wielu plików z limitami rozmiaru
Przesyłanie wieloczęściowe z interceptorami Multer to bezpłatna lekcja NestJS Enterprise Backend APIs na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej NestJS Enterprise Backend APIs, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs NestJS Enterprise Backend APIs zawiera 4 lekcji w sumie.
Części tej lekcji nie zostały jeszcze przetłumaczone i są wyświetlane po angielsku.
Why Multer for Uploads
HTTP file uploads use the multipart/form-data content type, which splits the request body into parts: text fields and binary file payloads separated by a boundary marker.
NestJS does not parse this format on its own. Instead it ships first-class wrappers around Multer, the de-facto Express middleware for multipart parsing. You consume Multer through interceptors rather than wiring middleware manually.
FileInterceptor— one file from a single fieldFilesInterceptor— many files from one fieldFileFieldsInterceptor— files across several named fields
This lesson focuses on the first two and on enforcing size limits.
Installing the Types
The interceptors live in @nestjs/platform-express, which is already present in a standard Nest app. You only need the Multer type definitions to type your handler parameters correctly.
Install the dev dependency so Express.Multer.File is recognized by TypeScript:
npm install -D @types/multer
// Now Express.Multer.File is available globally in TypeScript.
// It describes the in-memory/disk file object Multer attaches
// to the request, e.g. originalname, mimetype, size, buffer, path.Single File with FileInterceptor
Bind FileInterceptor('field') with @UseInterceptors, where the string is the name of the form-data field carrying the file. Then read the parsed file with the @UploadedFile() decorator.
The decorated parameter is a single Express.Multer.File. Notice the parameter name in the form does not need to match the handler argument — only the interceptor's field string matters.
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
@Controller('avatars')
export class AvatarsController {
@Post()
@UseInterceptors(FileInterceptor('avatar'))
upload(@UploadedFile() file: Express.Multer.File) {
return {
name: file.originalname,
type: file.mimetype,
size: file.size,
};
}
}Memory vs Disk Storage
By default Multer uses memory storage: the whole file lands in file.buffer as a Buffer. That is convenient for forwarding to S3 or processing in-process, but large files can exhaust RAM.
For local persistence use disk storage, where Multer streams to a path and gives you file.path instead of a buffer. Pass options as the second argument of the interceptor.
import { diskStorage } from 'multer';
import { extname } from 'path';
import { randomUUID } from 'crypto';
export const imageStorage = diskStorage({
destination: './uploads/images',
filename: (_req, file, cb) => {
const unique = randomUUID();
cb(null, `${unique}${extname(file.originalname)}`);
},
});
// Usage:
// @UseInterceptors(FileInterceptor('photo', { storage: imageStorage }))Enforcing a Size Limit
Never trust client-declared sizes. Cap the bytes Multer will accept via the limits.fileSize option (in bytes). When a file exceeds it, Multer aborts and Nest surfaces a 413-style error before your handler runs.
Combine fileSize with files to also bound the count of files in a multi-upload.
import { FileInterceptor } from '@nestjs/platform-express';
const FIVE_MB = 5 * 1024 * 1024;
@Post('avatar')
@UseInterceptors(
FileInterceptor('avatar', {
limits: { fileSize: FIVE_MB },
}),
)
upload(@UploadedFile() file: Express.Multer.File) {
return { stored: file.originalname };
}Computing Limits Safely
Express limits are expressed in raw bytes, which is easy to get wrong by an order of magnitude. A tiny pure helper keeps the math explicit and testable, and it runs anywhere with no framework.
Below, mb converts megabytes to bytes and we sanity-check a candidate upload size against a cap.
function mb(n: number): number {
return n * 1024 * 1024;
}
function withinLimit(sizeBytes: number, capMb: number): boolean {
return sizeBytes <= mb(capMb);
}
const FILE_CAP_MB = 5;
console.log('5MB in bytes:', mb(FILE_CAP_MB));
console.log(withinLimit(mb(4), FILE_CAP_MB)); // true
console.log(withinLimit(mb(6), FILE_CAP_MB)); // false
console.log(withinLimit(5_242_880, FILE_CAP_MB)); // true (exactly 5MB)Multiple Files with FilesInterceptor
FilesInterceptor('field', maxCount, options) accepts several files sent under the same field name. Read them with @UploadedFiles(), which yields an array.
The maxCount argument is a hard ceiling on how many files Nest will collect; extras trigger an error. Pair it with limits.fileSize for per-file byte caps.
import { Controller, Post, UploadedFiles, UseInterceptors } from '@nestjs/common';
import { FilesInterceptor } from '@nestjs/platform-express';
@Controller('gallery')
export class GalleryController {
@Post()
@UseInterceptors(
FilesInterceptor('photos', 10, {
limits: { fileSize: 5 * 1024 * 1024 },
}),
)
upload(@UploadedFiles() files: Express.Multer.File[]) {
return files.map((f) => ({ name: f.originalname, size: f.size }));
}
}Filtering by MIME Type
Size limits do not stop the wrong file type. Use fileFilter to accept or reject each part as it streams. Call the callback with (null, true) to keep a file or with an error to reject it.
Rejecting with a BadRequestException produces a clean 400 instead of a generic failure.
import { BadRequestException } from '@nestjs/common';
import { Request } from 'express';
export function imageFileFilter(
_req: Request,
file: Express.Multer.File,
cb: (error: Error | null, accept: boolean) => void,
) {
const allowed = ['image/png', 'image/jpeg', 'image/webp'];
if (!allowed.includes(file.mimetype)) {
return cb(new BadRequestException('Only PNG, JPEG, or WebP allowed'), false);
}
cb(null, true);
}Validating with ParseFilePipe
Nest's built-in ParseFilePipe validates the already-parsed file declaratively inside the handler. It composes validators like MaxFileSizeValidator and FileTypeValidator, returning a 422 when they fail.
This is complementary to Multer's limits: Multer guards the stream, the pipe guards your business rules and gives clearer error messages.
import {
ParseFilePipe,
MaxFileSizeValidator,
FileTypeValidator,
UploadedFile,
} from '@nestjs/common';
@Post('avatar')
@UseInterceptors(FileInterceptor('avatar'))
upload(
@UploadedFile(
new ParseFilePipe({
validators: [
new MaxFileSizeValidator({ maxSize: 5 * 1024 * 1024 }),
new FileTypeValidator({ fileType: /(png|jpe?g|webp)$/ }),
],
}),
)
file: Express.Multer.File,
) {
return { ok: true, name: file.originalname };
}Centralizing Config with a Factory
Repeating storage, limits, and filters on every route is error-prone. Extract a single MulterOptions object (or a factory) and reuse it. Enterprise apps often register defaults globally via MulterModule.register() and override per-route only when needed.
This keeps caps consistent and makes raising a limit a one-line change.
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
import { diskStorage } from 'multer';
import { imageFileFilter } from './image-file.filter';
export const imageUploadOptions: MulterOptions = {
storage: diskStorage({ destination: './uploads/images' }),
limits: { fileSize: 5 * 1024 * 1024, files: 10 },
fileFilter: imageFileFilter,
};
// @UseInterceptors(FilesInterceptor('photos', 10, imageUploadOptions))Handling the Size-Limit Error
When limits.fileSize is exceeded, Multer throws an error whose code is 'LIMIT_FILE_SIZE'. By default Nest wraps it, but you can map it to a friendly payload with an exception filter so clients get a clear, consistent message.
Translating low-level Multer codes into HTTP responses is a hallmark of production-grade upload endpoints.
import { ExceptionFilter, Catch, ArgumentsHost, HttpStatus } from '@nestjs/common';
import { MulterError } from 'multer';
import { Response } from 'express';
@Catch(MulterError)
export class MulterExceptionFilter implements ExceptionFilter {
catch(err: MulterError, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse<Response>();
const status =
err.code === 'LIMIT_FILE_SIZE'
? HttpStatus.PAYLOAD_TOO_LARGE
: HttpStatus.BAD_REQUEST;
res.status(status).json({ statusCode: status, message: err.message });
}
}Quick Check
Test your understanding of choosing the right interceptor and reading its result.
Recap
You can now wire multipart uploads end to end in NestJS:
- FileInterceptor('field', options) +
@UploadedFile()for one file. - FilesInterceptor('field', maxCount, options) +
@UploadedFiles()for many files under one field. - limits.fileSize (bytes) caps stream size; limits.files caps count; fileFilter rejects bad MIME types early.
- diskStorage vs memory storage decides whether you get
file.pathorfile.buffer. - ParseFilePipe with
MaxFileSizeValidator/FileTypeValidatorvalidates declaratively, and a MulterError filter mapsLIMIT_FILE_SIZEto a clean 413.
Centralize these options in one factory so limits stay consistent across every upload route.
Ucz się TypeScript dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 20
- Lekcje
- 76
Często zadawane pytania
Czy lekcja „Przesyłanie wieloczęściowe z interceptorami Multer” jest bezpłatna?
Tak — pełny tekst „Przesyłanie wieloczęściowe z interceptorami Multer” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu NestJS Enterprise Backend APIs, przejdź na CoddyKit PRO. Kurs NestJS Enterprise Backend APIs zawiera 4 lekcji w sumie.
Co nauczysz się w „Przesyłanie wieloczęściowe z interceptorami Multer”?
Skonfiguruj FileInterceptor i FilesInterceptor do obsługi przesyłania jednego lub wielu plików z limitami rozmiaru Ćwiczysz NestJS Enterprise Backend APIs z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć NestJS Enterprise Backend APIs?
Nie wymagamy żadnego doświadczenia. NestJS Enterprise Backend APIs w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Przesyłanie wieloczęściowe z interceptorami Multer”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji NestJS Enterprise Backend APIs?
Tak. Każda lekcja NestJS Enterprise Backend APIs zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Przesyłanie wieloczęściowe z interceptorami Multer
- Strumieniowanie dużych odpowiedzi za pomocą StreamableFile
- Bezpośrednie przesyłanie do S3 za pomocą presigned URL
- Potoki przetwarzania obrazów z Sharp