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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@habibulhasan/nestjs-file-uploader

v0.2.1

Published

A comprehensive file upload module for NestJS with support for multiple storage providers (AWS S3, Digital Ocean Spaces, Local Storage) using Strategy Pattern

Downloads

93

Readme

@habibulhasan/nestjs-file-uploader

npm version Downloads License

A comprehensive, production-ready file upload module for NestJS with support for multiple storage providers using the Strategy Pattern.

Features

Multiple Storage Providers

  • Local Filesystem Storage
  • AWS S3
  • Digital Ocean Spaces (with CDN support)
  • Linux Folder (with permissions management)

🎯 Strategy Pattern Implementation

  • Easily switch between storage providers
  • Runtime storage selection
  • Extensible architecture for custom providers

📦 Complete File Management

  • Single & bulk file uploads
  • Soft & hard delete with restore capability
  • File metadata (tags, description, custom fields)
  • Folder organization with tree structure
  • File search with advanced filters

🔒 Enterprise Features

  • File validation (size, MIME type, extensions)
  • Virus scanning hooks
  • Signed URLs for private files
  • Transaction support for bulk operations
  • Comprehensive error handling

📊 Advanced Querying

  • Pagination, sorting, filtering
  • Search by name, MIME type, folder, date range
  • Soft-deleted file management

🛠️ Developer Friendly

  • Full TypeScript support
  • Swagger/OpenAPI documentation
  • Dynamic module configuration
  • Database migrations included

Installation

npm install @habibulhasan/nestjs-file-uploader

Peer Dependencies

npm install @nestjs/common @nestjs/core @nestjs/platform-express @nestjs/typeorm typeorm reflect-metadata rxjs

Quick Start

1. Import the Module

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FileUploadModule } from '@habibulhasan/nestjs-file-uploader';
import { StorageType } from '@habibulhasan/nestjs-file-uploader';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      // your database config
    }),
    FileUploadModule.forRoot({
      storage: {
        [StorageType.LOCAL]: {
          uploadPath: './uploads',
          baseUrl: 'http://localhost:3000/uploads',
        },
      },
      defaultStorageType: StorageType.LOCAL,
    }),
  ],
})
export class AppModule {}

2. Run Database Migrations

Copy the migration template from src/migrations/CreateFileAndFolderTables.template.ts to your project's migrations folder and run:

npm run migration:run

3. Start Uploading Files

The module automatically registers REST endpoints:

# Upload a single file
POST /files/upload

# Upload multiple files
POST /files/upload/multiple

# List files
GET /files

# Get file by ID
GET /files/:id

# Delete file (soft)
DELETE /files/:id/soft

# Delete file (hard)
DELETE /files/:id/hard

Configuration

Local Storage

FileUploadModule.forRoot({
  storage: {
    [StorageType.LOCAL]: {
      uploadPath: './uploads',
      baseUrl: 'http://localhost:3000/uploads',
      createFolderIfNotExists: true,
    },
  },
});

AWS S3

FileUploadModule.forRoot({
  storage: {
    [StorageType.AWS_S3]: {
      region: 'us-east-1',
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
      bucket: 'my-bucket',
      acl: 'public-read', // or 'private'
    },
  },
});

Digital Ocean Spaces

FileUploadModule.forRoot({
  storage: {
    [StorageType.DIGITAL_OCEAN]: {
      region: 'nyc3', // or 'sgp1', 'fra1', etc.
      accessKeyId: process.env.DO_SPACES_KEY,
      secretAccessKey: process.env.DO_SPACES_SECRET,
      bucket: 'my-space',
      acl: 'public-read',
      cdnEndpoint: 'https://my-cdn.com', // optional CDN
    },
  },
});

Linux Folder (with permissions)

FileUploadModule.forRoot({
  storage: {
    [StorageType.LINUX_FOLDER]: {
      uploadPath: '/var/www/uploads',
      baseUrl: 'https://example.com/uploads',
      permissions: '0644', // file permissions
      owner: { uid: 1000, gid: 1000 }, // optional
    },
  },
});

Multiple Storage Providers

FileUploadModule.forRoot({
  storage: {
    [StorageType.LOCAL]: { /* config */ },
    [StorageType.AWS_S3]: { /* config */ },
    [StorageType.DIGITAL_OCEAN]: { /* config */ },
  },
  defaultStorageType: StorageType.AWS_S3,
  validation: {
    maxFileSize: 100 * 1024 * 1024, // 100MB
    allowedMimeTypes: ['image/jpeg', 'image/png', 'application/pdf', 'video/mp4', 'video/quicktime'],
    allowedExtensions: ['jpg', 'png', 'pdf', 'mp4', 'mov', 'avi'],
  },
});

Video Files & Compression Support

import {
  FileUploadModule,
  StorageType,
  VIDEO_MIME_TYPES,
  VIDEO_EXTENSIONS
} from '@habibulhasan/nestjs-file-uploader';

FileUploadModule.forRoot({
  storage: {
    [StorageType.AWS_S3]: {
      region: 'us-east-1',
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
      bucket: 'my-video-bucket',
      acl: 'public-read',
    },
  },
  validation: {
    maxFileSize: 500 * 1024 * 1024, // 500MB for videos
    allowedMimeTypes: VIDEO_MIME_TYPES, // Supports MP4, MOV, AVI, WebM, etc.
    allowedExtensions: VIDEO_EXTENSIONS,
    compression: {
      enabled: true,
      quality: 23, // Video quality (0-51, lower = better)
      videoBitrate: '2M', // 2 Mbps
      audioCodec: 'aac',
      videoCodec: 'libx264',
      format: 'mp4',
    },
  },
});

Supported Video Formats:

  • MP4 (.mp4)
  • QuickTime (.mov)
  • AVI (.avi)
  • WebM (.webm)
  • MPEG (.mpeg, .mpg)
  • Windows Media Video (.wmv)
  • Flash Video (.flv)
  • 3GPP (.3gp)
  • Matroska (.mkv)

Supported Image Formats:

  • JPEG (.jpg, .jpeg)
  • PNG (.png)
  • GIF (.gif)
  • WebP (.webp)
  • SVG (.svg)
  • BMP (.bmp)
  • TIFF (.tiff)

Other Supported Formats:

  • Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX
  • Audio: MP3, M4A, WAV, OGG, FLAC
  • Archives: ZIP, RAR, 7Z, TAR, GZ

## Async Configuration

```typescript
FileUploadModule.forRootAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    storage: {
      [StorageType.AWS_S3]: {
        region: configService.get('AWS_REGION'),
        accessKeyId: configService.get('AWS_ACCESS_KEY_ID'),
        secretAccessKey: configService.get('AWS_SECRET_ACCESS_KEY'),
        bucket: configService.get('AWS_BUCKET'),
      },
    },
  }),
  inject: [ConfigService],
});

Usage Examples

Upload a File

import { Controller, Post, UseInterceptors, UploadedFile } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { FileService, FileUploadDto, StorageType } from '@habibulhasan/nestjs-file-uploader';

@Controller('upload')
export class UploadController {
  constructor(private readonly fileService: FileService) {}

  @Post()
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(@UploadedFile() file: Express.Multer.File) {
    return this.fileService.uploadFile(file, {
      storageType: StorageType.AWS_S3,
      tags: ['user-avatar'],
      isPublic: true,
      uploadedBy: 'user-123',
    });
  }
}

List Files with Filters

const files = await this.fileService.findAll({
  page: 1,
  limit: 20,
  search: 'document',
  mimetype: 'application/pdf',
  tags: ['important'],
  minSize: 1024,
  maxSize: 1024 * 1024 * 10,
  createdAfter: new Date('2024-01-01'),
  sortBy: 'createdAt',
  sortOrder: 'DESC',
});

Bulk Delete Files

const result = await this.fileService.bulkSoftDelete({
  fileIds: ['id1', 'id2', 'id3'],
  soft: true,
  deletedBy: 'admin-123',
});

console.log(`Deleted ${result.successCount} files`);

Get Signed URL for Private Files

const url = await this.fileService.getSignedUrl('file-id', 3600); // expires in 1 hour

Working with Folders

import { FolderService } from '@habibulhasan/nestjs-file-uploader';

// Create folder
const folder = await this.folderService.create({
  name: 'Documents',
  description: 'User documents',
  parentId: null, // root level
});

// Get folder tree
const tree = await this.folderService.getTree();

// Move folder
await this.folderService.move(folderId, {
  targetParentId: newParentId,
});

API Endpoints

Files

  • POST /files/upload - Upload single file
  • POST /files/upload/multiple - Upload multiple files
  • GET /files - List files (with filters)
  • GET /files/:id - Get file by ID
  • GET /files/:id/signed-url - Get signed URL
  • PATCH /files/:id/metadata - Update file metadata
  • DELETE /files/:id/soft - Soft delete
  • DELETE /files/:id/hard - Hard delete
  • POST /files/:id/restore - Restore deleted file
  • POST /files/bulk/delete - Bulk delete
  • POST /files/bulk/restore - Bulk restore
  • PATCH /files/bulk/metadata - Bulk update metadata

Folders

  • POST /folders - Create folder
  • GET /folders - List all folders
  • GET /folders/tree - Get folder tree
  • GET /folders/:id - Get folder by ID
  • GET /folders/:id/stats - Get folder stats
  • GET /folders/:id/children - Get direct children
  • GET /folders/:id/descendants - Get all descendants
  • GET /folders/:id/ancestors - Get ancestors (path to root)
  • PATCH /folders/:id - Update folder
  • PATCH /folders/:id/move - Move folder
  • DELETE /folders/:id/soft - Soft delete
  • DELETE /folders/:id/hard - Hard delete (requires empty or force)
  • POST /folders/:id/restore - Restore deleted folder

Database Schema

Files Table

  • id (uuid, primary key)
  • name, originalName, path, url
  • size, mimetype, extension
  • storageType, storageBucket, storageKey
  • folderId (foreign key)
  • uploadedBy, deletedBy
  • description, tags, metadata (jsonb)
  • isPublic, checksum
  • createdAt, updatedAt, deletedAt (soft delete)

Folders Table

  • id (uuid, primary key)
  • name, description, path
  • parentId (self-referencing foreign key)
  • fileCount, totalSize
  • metadata (jsonb)
  • isPublic
  • createdAt, updatedAt, deletedAt

Advanced Features

Custom Storage Strategy

import { IStorageStrategy } from '@habibulhasan/nestjs-file-uploader';

class MyCustomStorageStrategy implements IStorageStrategy {
  async upload(file, filename, options) {
    // Your custom upload logic
  }
  // ... implement other methods
}

// Register it
storageFactory.registerStrategy(StorageType.CUSTOM, new MyCustomStorageStrategy());

Virus Scanning Hook

FileUploadModule.forRoot({
  storage: { /* ... */ },
  validation: {
    virusScanHook: async (file) => {
      const isClean = await myVirusScanner.scan(file.buffer);
      return isClean; // return true if safe
    },
  },
});

Testing

# Unit tests
npm test

# E2E tests
npm run test:e2e

# Test coverage
npm run test:cov

License

MIT

Contributing

Contributions welcome! Please read our contributing guidelines.

Support

For issues and questions, please use GitHub Issues.


Made with ❤️ by PocketSchool