Uploadex is a provider-agnostic, production-ready file upload module for NestJS. Built with a stream-first engine, strict validation, and support for S3, GCS, Azure, Cloudinary, and local uploads — all with one config, one line, and total control
One config. One interceptor. Total control.
Stream-first & buffer-aware upload engine:
Multiple provider support:
Built-in file validation system:
Automatic safe upload system:
No download data available
No tracked packages depend on this.
Signed URL upload support:
Emulator support (for local development):
Filename sanitization:
Multi-file upload made simple:
Fully configurable via registerAsync():
ConfigModuleInterceptor-ready usage:
@UseInterceptors(UploadexInterceptor)@UploadedFile() / @UploadedFiles()Framework-ready:
npm install uploadex
# or
yarn add uploadex
// uploads.controller.ts
@Post('upload')
@UseInterceptors(UploadexInterceptor('file'))
upload(@UploadedFile() file: Express.Multer.File) {
return this.uploadexService.handleSingleFileUpload(file);
}
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { UploadsModule } from 'uploadex';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
UploadsModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
provider: config.get<'s3' | 'azure' | 'gcs' | 'cloudinary' | 'local'>('UPLOAD_PROVIDER'),
config: {
bucket: config.get('S3_BUCKET') ?? '',
region: config.get('S3_REGION') ?? '',
accessKeyId: config.get('S3_ACCESS_KEY') ?? '',
secretAccessKey: config.get('S3_SECRET') ?? '',
endpoint: config.get('S3_ENDPOINT') ?? '', // For emulator or self-hosted S3
},
maxFileSize: parseInt(config.get('MAX_FILE_SIZE') ?? '10485760'), // 10MB
maxFiles: parseInt(config.get('MAX_FILES') ?? '5'), // Up to 5 files
allowedMimeTypes: ['image/jpeg', 'image/png', 'application/pdf'], // Accept only specific MIME types
allowedExtensions: ['.jpg', '.jpeg', '.png', '.pdf'], // Restrict to safe extensions
maxSafeMemorySize: parseInt(config.get('MAX_SAFE_MEMORY_SIZE') ?? '5242880'), // Buffer small files (5MB), stream large
uploadRetries: parseInt(config.get('UPLOAD_RETRIES') ?? '2'), // Retry twice on failure
uploadTimeoutMs: parseInt(config.get('UPLOAD_TIMEOUT_MS') ?? '15000'), // 15s timeout per upload
debug: true, // Enable debug logs
}),
}),
],
controllers: [UploadController],
providers: [UploadService],
})
export class AppModule {}
See the full documentation → https://www.uploadex.dev
Covers:
Looking for ready-to-use examples?
👉 Check out the full Uploadex Examples Repository Includes working setups for Local, S3, Azure, GCS, and Cloudinary — all pre-configured.
Yassine El Idrissi — Portfolio
Creator of Uploadex, passionate about backend architecture and open source.
If Uploadex saved you time — give it a ⭐ on GitHub
Tweet about it. Share it with friends. Help us grow the upload revolution.
MIT © 2025 Yassine El Idrissi