- Single file upload to an Amazon S3 bucket
- Support for dynamic paths, upload files wherever you want!
- Generate thumbnail image along with the original
- Resize single image or even make it into different sizes
- Load AWS S3 configuration at runtime
NPM
$ npm i -s nestjs-multer-extended
Yarn
$ yarn add nestjs-multer-extended
Once the installation process is complete, we can import the module either synchronously or asynchronosly into the root AppModule
.
Β
import { Module } from '@nestjs/common';
import { MulterExtendedModule } from 'nestjs-multer-extended';
@Module({
imports: [
MulterExtendedModule.register({
accessKeyId: 'YOUR_AWS_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_AWS_SECRET_ACCESS_KEY',
region: 'AWS_REGION_NEAR_TO_YOU',
bucket: 'YOUR_S3_BUCKET_NAME',
basePath: 'ROOT_DIR_OF_ASSETS',
fileSize: 1 * 1024 * 1024,
}),
],
})
export class AppModule {}
In this example, the module integrates with the awesome nestjs-config package.
useFactory
should return an object with MulterExtendedS3Options interface or undefined.
import { Module } from '@nestjs/common';
import { MulterExtendedModule } from 'nestjs-multer-extended';
import { ConfigService } from 'nestjs-config';
@Module({
imports: [
MulterExtendedModule.registerAsync({
useFactory: (config: ConfigService) => config.get('s3'),
inject: [ConfigService],
}),
],
})
export class AppModule {}
Note: You can import this module from not only the root module of your app but also from other feature modules where you want to use it.
Β
To upload a single file, simply tie the AmazonS3FileInterceptor()
interceptor to the route handler and extract file
from the request using the @UploadedFile()
decorator.
import { Controller, Post, UseInterceptors, UploadedFile } from '@nestjs/common';
import { AmazonS3FileInterceptor } from 'nestjs-multer-extended';
@Controller()
export class AppController {
@Post('upload')
@UseInterceptors(AmazonS3FileInterceptor('file'))
uploadFile(@UploadedFile() file) {
console.log(file);
}
}
In this example, uploadFile()
method will upload a file under the base path you have configured earlrier.
The AmazonS3FileInterceptor()
decorator takes two arguments:
fieldName
: string that supplies the name of the field from the HTML form that holds a file.options
: optional object of typeMulterExtendedOptions
. (mode details here)
What if you wanted to upload a file in a different location under the base path? Thankfully, AmazonS3FileInterceptor()
decorator accepts dynamicPath
property as a second argument option. Pass the string path as shown below:
@Post('upload')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
dynamicPath: 'aec16138-a75a-4961-b8c1-8e803b6bf2cf'
}),
)
uploadFile(@UploadedFile() file) {
console.log(file);
}
In this example, uploadFile()
method will upload a file in ${basePath}/aec16138-a75a-4961-b8c1-8e803b6bf2cf/${originalname}
.
If you want to resize the file before the upload, you can pass on the resize property as follows:
@Post('upload')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
resize: { width: 500, height: 400 },
}),
)
uploadFile(@UploadedFile() file) {
console.log(file);
}
You can pass an array of size options to resize a single image into different sizes as follows:
@Post('upload')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
resizeMultiple: [
{ suffix: 'sm', width: 200, height: 200 },
{ suffix: 'md', width: 300, height: 300 },
{ suffix: 'lg', width: 400, height: 400 },
],
}
)
uploadFile(@UploadedFile() file) {
console.log(file);
}
Not only creating a thumbnail image but also willing to change the file size limit, you can pass the properties as follows:
@Post('upload')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
thumbnail: { suffix: 'thumb', width: 200, height: 200 },
limits: { fileSize: 7 * 1024 * 1024 },
}),
)
uploadFile(@UploadedFile() file) {
console.log(file);
}
In this example, uploadFile()
method will upload both thumbnail and original images.
Β
MulterExtendedModule
requires an object with the following interface:
interface MulterExtendedS3Options {
/**
* AWS Access Key ID
*/
readonly accessKeyId: string;
/**
* AWS Secret Access Key
*/
readonly secretAccessKey: string;
/**
* Default region name
* default: us-west-2
*/
readonly region: string;
/**
* The name of Amazon S3 bucket
*/
readonly bucket: string;
/**
* The base path where you want to store files in
*/
readonly basePath: string;
/**
* Optional parameter for Access control level for the file
* default: public-read
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl
*/
readonly acl?: string;
/**
* Optional parameter for the file size
* default: 3MB
*/
readonly fileSize?: number | string;
/**
* Optional parameter for a custom logger
* default: NestJS built-in text-based logger
* @see https://docs.nestjs.com/techniques/logger
*/
readonly logger?: LoggerService;
}
Key | Default | Description | Example |
---|---|---|---|
dynamicPath |
undefined | The name that you assign to an S3 object | "aec16138-a75a-4961-b8c1-8e803b6bf2cf/random/dir" |
fileFilter |
Accepts JPEG, PNG types only | Function to control which files are accepted | |
limits |
3MB | Limits of the uploaded data | 5242880 (in bytes) |
resize |
undefined | Resize a single file | { width: 300, height: 350 } |
resizeMultiple |
undefined | Resize a single file into different sizes (Array<object> ) |
[{ suffix: 'md', width: 300, height: 350 }, { suffix: 'sm', width: 200, height: 200 }] |
thumbnail |
undefined | Create a thumbnail image (object ) |
{ suffix: 'thumbnail', width: 200, height: 200 } |
You could help me out for some coffees π₯€ or give us a star βοΈ
Thanks goes to these wonderful people (emoji key):
Minsung Kim π» π§ π π π€ |
Jay McDoniel π€ π§ π π» |
Semin Lee π¨ |
This project follows the all-contributors specification. Contributions of any kind welcome!