1.0.0 • Published 7 months ago

@khoativi/nestjs-upload-file v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

@khoativi/nestjs-upload-file

@khoativi/nestjs-upload-file helps you easily upload, validate, manage, and serve files via S3-compatible storage systems. It also integrates seamlessly with CDN providers, and supports access control via ACL.

✨ Key Features

  • ⚙️ Pluggable S3 Storage — Upload to AWS S3 or any compatible endpoint (MinIO, Wasabi, etc.)
  • High-Speed Upload — Multipart support for large files via @aws-sdk/lib-storage
  • 🛡️ Access Control — Public/private file ACL management
  • 🌐 CDN Integration — Return CDN URLs for public access
  • 🎛️ MIME & Size Validation — Configurable restrictions
  • 📦 Framework Agnostic — Works with both Express and Fastify
  • 🧪 Fully Tested — Comes with Jest setup and coverage support

📦 Installation

Using npm:

npm install @khoativi/nestjs-upload-file @aws-sdk/client-s3

Using yarn:

yarn add @khoativi/nestjs-upload-file @aws-sdk/client-s3

Using pnpm:

pnpm add @khoativi/nestjs-upload-file @aws-sdk/client-s3

🧰 Usage

Express (default)

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

Fastify

// main.ts
import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication
} from '@nestjs/platform-fastify';
import multipart from '@fastify/multipart';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );
  await app.register(multipart);
  await app.listen(3000, '0.0.0.0');
}
bootstrap();

Register the Module

// app.module.ts
import { FileUploadModule } from '@khoativi/nestjs-upload-file';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot(),
    FileUploadModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        storage: 's3',
        bucketName: config.get('AWS_BUCKET_NAME'),
        s3Options: {
          credentials: {
            accessKeyId: config.get('AWS_ACCESS_KEY'),
            secretAccessKey: config.get('AWS_SECRET_KEY')
          },
          region: config.get('AWS_REGION_NAME'),
          endpoint: config.get('AWS_ENDPOINT_URL')
        },
        cdnBaseUrl: config.get('CDN_BASE_URL'),
        allowedMimeTypes: ['image/png', 'image/jpeg'],
        maxFileSize: 5 * 1024 * 1024 // 5MB
      })
    })
  ]
})
export class AppModule {}

Example Controller

// file-upload.controller.ts
import {
  Controller,
  Post,
  UploadedFile,
  UseInterceptors,
  Body
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { FileUploadService, S3ObjectACL } from '@khoativi/nestjs-upload-file';

@Controller('upload')
export class FileUploadController {
  constructor(private readonly uploadService: FileUploadService) {}

  @Post('single')
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(
    @UploadedFile() file: Express.Multer.File,
    @Body('acl') acl: S3ObjectACL
  ) {
    const result = await this.uploadService.uploadFile(file.originalname, {
      buffer: file.buffer,
      acl
    });
    return result;
  }
}

⚙️ Configuration Options

OptionTypeRequiredDescription
storage's3'The storage backend (currently only S3 supported)
bucketNamestringName of the S3 bucket
s3OptionsS3ClientConfigConfiguration for the S3 client (region, credentials, endpoint, etc.)
cdnBaseUrlstringOptional CDN base URL (e.g. https://cdn.example.com)
allowedMimeTypesstring[]List of allowed MIME types
maxFileSizenumberMax file size in bytes

🐛 Issues and Contributing

Please open an issue if you find a bug or have a feature request. We welcome contributions via pull requests.

📄 License

MIT License © Khoa Trần