npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@elchinabilov/nestjs-aws-file-storage

v1.4.7

Published

AWS File storage for NestJS

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-storage

Prerequisites

  • 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-name

2. 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/:id

Bulk 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 publicRoutes is set to true for a route, the @IsPublic() decorator is applied dynamically, making the endpoint accessible without authentication.
  • Protected Routes: When publicRoutes is set to false or 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

  • PDF
  • 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.ext

Error 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