Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jeffminsungkim/nestjs-multer-extended
πͺ Extended MulterModule for NestJS with flexible S3 upload and helpful features
https://github.com/jeffminsungkim/nestjs-multer-extended
aws-s3 dynamic-module extended multer nestjs s3
Last synced: 3 days ago
JSON representation
πͺ Extended MulterModule for NestJS with flexible S3 upload and helpful features
- Host: GitHub
- URL: https://github.com/jeffminsungkim/nestjs-multer-extended
- Owner: jeffminsungkim
- License: mit
- Created: 2020-01-16T09:36:03.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2024-10-23T11:22:46.000Z (3 months ago)
- Last Synced: 2024-10-29T17:23:33.833Z (3 months ago)
- Topics: aws-s3, dynamic-module, extended, multer, nestjs, s3
- Language: TypeScript
- Homepage:
- Size: 4.49 MB
- Stars: 203
- Watchers: 2
- Forks: 47
- Open Issues: 63
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
## Features
- 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## Installation
**NPM**
```bash
$ npm i -s nestjs-multer-extended
```**Yarn**
```bash
$ yarn add nestjs-multer-extended
```## Getting started
Once the installation process is complete, we can import the module either synchronously or asynchronosly into the root `AppModule`.
Β
### Synchronous configuration
```typescript
import { Module } from '@nestjs/common';
import { MulterExtendedModule } from 'nestjs-multer-extended';@Module({
imports: [
MulterExtendedModule.register({
awsConfig: {
accessKeyId: 'YOUR_AWS_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_AWS_ACCESS_KEY_ID',
region: 'AWS_REGION_NEAR_TO_YOU',
// ... any options you want to pass to the AWS instance
},
bucket: 'YOUR_S3_BUCKET_NAME',
basePath: 'ROOT_DIR_OF_ASSETS',
fileSize: 1 * 1024 * 1024,
}),
],
})
export class AppModule {}
```### Asynchronous configuration
In this example, the module integrates with the awesome [nestjs-config](https://github.com/nestjsx/nestjs-config) package.
`useFactory` should return an object with [MulterExtendedS3Options interface](#MulterExtendedS3Options) or undefined.
```typescript
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.
```javascript
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 type `MulterExtendedOptions`. (mode details [**here**](#MulterExtendedOptions))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:
```javascript
@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}`.
Route parameters can also be used as a key. For example, if you have the route `/user/:name`, then pass the `name` into the `dynamicPath` property as a value.
```javascript
@Post('user/:name')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
dynamicPath: 'name'
}),
)
uploadFile(@UploadedFile() file) {
// POST /user/jeffminsungkim
console.log(file);
// => YOUR-BASE-PATH/jeffminsungkim/filename.png
}@Post('user/:name/team/:no')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
dynamicPath: 'no'
}),
)
uploadFile(@UploadedFile() file) {
// POST /user/jeffminsungkim/team/8987
console.log(file);
// => YOUR-BASE-PATH/8987/filename.png
}@Post('user/:name/team/:no')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
dynamicPath: ['name', 'no']
}),
)
uploadFile(@UploadedFile() file) {
// POST /user/jeffminsungkim/team/8987
console.log(file);
// => YOUR-BASE-PATH/jeffminsungkim/8987/filename.png
}
```Β
You may want to store the file with an arbitrary name instead of the original file name. You can do this by passing the `randomFilename` property attribute set to `true` as follows:
```javascript
@Post('upload')
@UseInterceptors(
AmazonS3FileInterceptor('file', {
randomFilename: true
}),
)
uploadFile(@UploadedFile() file) {
console.log(file);
}
```If you want to resize the file before the upload, you can pass on the `resize` property as follows:
```javascript
@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:
```javascript
@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:
```javascript
@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.
Β
### MulterExtendedS3Options
`MulterExtendedModule` requires an object with the following interface:
```typescript
interface MulterExtendedS3Options {
/**
* AWS Access Key ID
* @deprecated v2 use awsConfig instead
*/
readonly accessKeyId?: string;
/**
* AWS Secret Access Key
* @deprecated v2 use awsConfig instead
*/
readonly secretAccessKey?: string;
/**
* Default region name
* default: us-west-2
* @deprecated v2 use awsConfig instead
*/
readonly region?: string;
/**
* AWS Config
*/
readonly awsConfig?: ConfigurationOptions & ConfigurationServicePlaceholders & APIVersions & {[key: string]: any};
/**
* S3 Config
*/
readonly s3Config?: AWS.S3.Types.ClientConfiguration;
/**
* 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;
/**
* AWS Endpoint
* @deprecated v2 use s3Config instead
*/
readonly endpoint?: 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;
}
```### MulterExtendedOptions
Key | Default | Description | Example
--- | --- | --- | ---
`dynamicPath` | undefined | The name that you assign to an S3 object | "aec16138-a75a-4961-b8c1-8e803b6bf2cf/random/dir"
`randomFilename` | undefined | If this property sets to true, a random file name will be generated | "aec16138-a75a-4961-b8c1-8e803b6bf2cf"
`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`) | [{ 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 }## Support
You could help me out for some coffees π₯€ or give us a star βοΈ
## Maintainers
- [Minsung Kim](https://github.com/jeffminsungkim)
## Contributors β¨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Minsung Kim
π» π§ π π π€ β οΈ
Jay McDoniel
π€ π§ π π»
semin3276
π¨
RenΓ© Volbach
π» β οΈ
gimyboya
π»
dineshsalunke
π» π
Michael Wolz
π» π
visurel
π» π
Keith Kikta
π§ π»
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!