@elchinabilov/nestjs-aws-file-storage
v1.4.7
Published
AWS File storage for NestJS
Maintainers
Readme
AWS File storage package for NestJS
A comprehensive AWS S3 file storage module for NestJS applications with automatic image optimization and multiple format conversions.
Features
- 🚀 Easy Integration: Simple setup with NestJS dependency injection
- 📁 AWS S3 Integration: Seamless file upload to Amazon S3
- 🖼️ Automatic Image Optimization: Built-in image resizing and format conversion
- 🔄 Multiple Conversions: Generate different image sizes (thumbnails, medium, large, etc.)
- 📊 Database Tracking: Store file metadata in your database
- 🛡️ TypeScript Support: Full TypeScript support with type definitions
- 🎯 Sharp Integration: High-performance image processing with Sharp
- 📝 RESTful API: Ready-to-use controllers for file operations
Installation
npm install @elchinabilov/nestjs-aws-file-storagePrerequisites
- Node.js (v16 or higher)
- NestJS application
- AWS S3 bucket
- TypeORM (for database integration)
Configuration
1. Environment Variables
Create a .env file in your project root:
# AWS Configuration
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_S3_BUCKET=your-bucket-name2. Database Setup
Make sure you have TypeORM configured in your NestJS application. The module will automatically create the required files table.
3. Module Configuration
Import the module in your app.module.ts:
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { TypeOrmModule } from "@nestjs/typeorm";
import { FileStorageModule } from "@elchinabilov/nestjs-aws-file-storage";
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRoot({
// Your TypeORM configuration
}),
FileStorageModule.forRoot({
aws: {
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
bucket: process.env.AWS_S3_BUCKET,
},
conversions: [
{ suffix: "thumbnail", width: 150 },
{ suffix: "small", width: 300 },
{ suffix: "medium", width: 600 },
{ suffix: "large", width: 1200 },
],
publicRoutes: {
upload: true, // POST /files - public (no authentication required)
delete: false, // DELETE /files/:id - protected (authentication required)
bulkDelete: false, // DELETE /files/bulk - protected (authentication required)
},
}),
],
})
export class AppModule {}Usage
Basic File Upload
The module provides a ready-to-use controller at /files endpoint:
// POST /files
// Content-Type: multipart/form-data
// Body: files (form field)Using the Service Directly
import { Injectable } from "@nestjs/common";
import { FileStorageService } from "@elchinabilov/nestjs-aws-file-storage";
@Injectable()
export class MyService {
constructor(private readonly fileStorageService: FileStorageService) {}
async uploadFile(file: Express.Multer.File) {
return await this.fileStorageService.upload(file);
}
async deleteFile(fileId: string) {
return await this.fileStorageService.delete(fileId);
}
async uploadFromUrl(url: string) {
return await this.fileStorageService.uploadFromUrl(url);
}
}File Entity
The uploaded files are stored in the database with the following structure:
interface FileEntity {
id: string; // UUID
originalName: string; // Original filename
mimeType: string; // MIME type
size: number; // File size in bytes
conversions: Record<string, string>; // URLs for different sizes
createdAt: Date; // Upload timestamp
}Image Conversions
For image files (JPEG, PNG), the module automatically generates multiple sizes:
// Example response for an uploaded image
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"originalName": "photo.jpg",
"mimeType": "image/jpeg",
"size": 1024000,
"conversions": {
"thumbnail": "https://your-bucket.s3.amazonaws.com/uploads/123e4567-e89b-12d3-a456-426614174000/thumbnail.webp",
"small": "https://your-bucket.s3.amazonaws.com/uploads/123e4567-e89b-12d3-a456-426614174000/small.webp",
"medium": "https://your-bucket.s3.amazonaws.com/uploads/123e4567-e89b-12d3-a456-426614174000/medium.webp",
"large": "https://your-bucket.s3.amazonaws.com/uploads/123e4567-e89b-12d3-a456-426614174000/large.webp"
},
"createdAt": "2024-01-01T00:00:00.000Z"
}API Endpoints
Upload File
POST /files
Content-Type: multipart/form-data
Body:
- file: File (required)Response:
{
"id": "uuid",
"originalName": "filename.jpg",
"mimeType": "image/jpeg",
"size": 1024000,
"conversions": {
"thumbnail": "https://...",
"small": "https://...",
"medium": "https://...",
"large": "https://..."
},
"createdAt": "2024-01-01T00:00:00.000Z"
}Upload From URL
POST /files/url
Body:
- url: string (required)Response: Same structure as file upload. For images (JPEG/PNG), conversions are generated as WebP. For non-images, a single url is returned in conversions.
Delete File
DELETE /files/:idBulk Delete
DELETE /files/bulk
Body:
- ids: string[] (required)Public Routes Configuration
The module allows you to configure which routes should be public (no authentication required) and which should be protected (authentication required). This is useful when you want to allow public file uploads but protect file deletion operations.
Example Public Routes Configuration
FileStorageModule.forRoot({
aws: {
region: "us-east-1",
accessKeyId: "your-key",
secretAccessKey: "your-secret",
bucket: "your-bucket",
},
conversions: [
{ suffix: "thumbnail", width: 150 },
{ suffix: "small", width: 300 },
],
publicRoutes: {
upload: true, // POST /files - public (no authentication required)
// When upload is public, POST /files/url is also public
delete: false, // DELETE /files/:id - protected (authentication required)
bulkDelete: false, // DELETE /files/bulk - protected (authentication required)
},
});Route Behavior
- Public Routes: When
publicRoutesis set totruefor a route, the@IsPublic()decorator is applied dynamically, making the endpoint accessible without authentication. - Protected Routes: When
publicRoutesis set tofalseor omitted, the route requires authentication (depends on your authentication setup). - Mixed Configuration: You can have some routes public and others protected. For example, allow public uploads but protect delete operations.
- Dynamic Application: The module automatically applies the
@IsPublic()decorator to the specified routes based on your configuration.
Configuration Options
FileModuleOptions
interface FileModuleOptions {
aws: {
region: string; // AWS region
accessKeyId: string; // AWS access key ID
secretAccessKey: string; // AWS secret access key
bucket: string; // S3 bucket name
};
conversions: Array<{
suffix: string; // Conversion name (e.g., 'thumbnail', 'medium')
width: number; // Image width in pixels
}>;
publicRoutes?: {
upload?: boolean; // Make upload endpoint public (no authentication required)
delete?: boolean; // Make delete endpoint public (no authentication required)
bulkDelete?: boolean; // Make bulk delete endpoint public (no authentication required)
};
}Example Configuration
FileStorageModule.forRoot({
aws: {
region: "us-east-1",
accessKeyId: "AKIAIOSFODNN7EXAMPLE",
secretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
bucket: "my-app-files",
},
conversions: [
{ suffix: "thumbnail", width: 150 },
{ suffix: "small", width: 300 },
{ suffix: "medium", width: 600 },
{ suffix: "large", width: 1200 },
{ suffix: "xlarge", width: 1920 },
],
});Supported File Types
Images (with automatic optimization)
- JPEG/JPG
- PNG
Images are automatically converted to WebP format for better compression and performance.
Other Files
- Documents (DOC, DOCX, TXT, etc.)
- Videos (MP4, AVI, MOV, etc.)
- Audio (MP3, WAV, etc.)
- Archives (ZIP, RAR, etc.)
File Structure
uploads/
├── {uuid}/
│ ├── thumbnail.webp
│ ├── small.webp
│ ├── medium.webp
│ ├── large.webp
│ └── original-filename.extError Handling
The module includes comprehensive error handling for:
- Invalid file types
- Upload failures
- AWS S3 connection issues
- Database errors
- Image processing errors
Performance Considerations
- Images are processed asynchronously
- WebP format is used for better compression
- Multiple image sizes are generated in parallel
- Database operations are optimized
Security
- File type validation
- Size limits (configure in your NestJS app)
- Secure AWS credentials handling
- UUID-based file naming for security
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Elchin Abilov
- Email: [email protected]
