-
-
Save sandeepsuvit/1345ab69eb819164ab497ad07c589d8d to your computer and use it in GitHub Desktop.
nestjs file upload using multer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# File properties | |
## | |
UPLOAD_LOCATION=/Users/dummyusername/Documents/temp/nvaluate | |
# Max 5Mb allowed | |
MAX_FILE_SIZE=5 | |
MAX_FILE_COUNTS=20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { IsNotEmpty, IsBoolean, ValidateIf } from 'class-validator'; | |
import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger'; | |
export class AbstractAttachmentDto { | |
@ApiModelProperty() | |
@IsNotEmpty() | |
fileName: string; | |
@ApiModelProperty() | |
@IsNotEmpty() | |
originalFileName: string; | |
@ApiModelProperty() | |
@IsNotEmpty() | |
mediaType: string; | |
@ApiModelProperty() | |
@IsNotEmpty() | |
fileSize: number; | |
@ApiModelPropertyOptional({ default: false }) | |
@IsBoolean() | |
isCommentAttachment: boolean = false; | |
// Validate this field if the attachment is not for a comment | |
@ApiModelProperty({ required: this.isCommentAttachment ? true : false }) | |
@ValidateIf(o => o.isCommentAttachment ? false : true) | |
@IsNotEmpty() | |
parent?: string; | |
constructor( | |
fileName: string, | |
originalFileName: string, | |
mediaType: string, | |
fileSize: number, | |
isCommentAttachment: boolean, | |
parent?: string, | |
) { | |
this.fileName = fileName; | |
this.originalFileName = originalFileName; | |
this.mediaType = mediaType; | |
this.fileSize = fileSize; | |
this.parent = parent; | |
this.isCommentAttachment = isCommentAttachment; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@nestjs/common'; | |
import { InjectModel } from '@nestjs/mongoose'; | |
import { Model } from 'mongoose'; | |
import { IAttachment } from '../../core/interfaces/attachment.interface'; | |
import { AbstractAttachmentDto } from './../dtos/abstract-attachment.dto'; | |
@Injectable() | |
export class AbstractAttachmentService { | |
constructor( | |
@InjectModel('Attachment') private readonly attachmentModel: Model<IAttachment>, | |
) {} | |
/** | |
* Add attachment | |
* | |
* @param {any[]} files | |
* @param {string} userId | |
* @returns {Promise<IAttachment[]>} | |
* @memberof AbstractAttachmentService | |
*/ | |
async addAttachments(files: any[], userId: string): Promise<IAttachment[]> { | |
const attachments: IAttachment[] = []; | |
for (const file of files) { | |
// Get the file properties | |
const { filename, originalname, mimetype, size } = file; | |
// Form the attachment object | |
let attachment = new AbstractAttachmentDto(filename, originalname, mimetype, size, true); | |
// Collect all attachments | |
attachments.push(new this.attachmentModel(attachment)); | |
} | |
// Persist the data | |
return await this.attachmentModel.insertMany(attachments); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createParamDecorator } from '@nestjs/common'; | |
// Decorator function to extract the data | |
export const AuthUser = createParamDecorator((data, req) => data ? req.authInfo.user[data] : req.authInfo.user); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Body, Controller, Post, UploadedFiles, UseGuards, UseInterceptors, Get, Query } from '@nestjs/common'; | |
import { FilesInterceptor } from '@nestjs/platform-express/multer'; | |
import { ApiBadRequestResponse, ApiBearerAuth, ApiConsumes, ApiCreatedResponse, ApiForbiddenResponse, ApiImplicitFile, ApiOperation, ApiUseTags, ApiOkResponse } from '@nestjs/swagger'; | |
import { UploadTypesEnum } from '../core/enums/upload-types.enum'; | |
import { AuthUser } from './../shared/decorators/auth-user.decorator'; | |
import { AuthGuard } from './../shared/guards/auth.gaurd'; | |
import { RolesGuard } from './../shared/guards/roles.guard'; | |
import { MulterUtils } from './../shared/services/multer-utils.service'; | |
import { AbstractAttachmentService } from './services/abstract-attachment.service'; | |
/** | |
* Controller to manage all common enpoints | |
* | |
* @export | |
* @class CommonController | |
*/ | |
@ApiUseTags('common') | |
@Controller('common') | |
export class CommonController { | |
constructor( | |
private attachmentService: AbstractAttachmentService, | |
) {} | |
/** | |
* Upload attachments | |
* Note: The controller method | |
* | |
* @param {string} authUserId | |
* @param {any[]} files | |
* @memberof CommonController | |
*/ | |
@Post('/actions/addAttachments') | |
@ApiOperation({ title: 'Upload attachments' }) | |
@ApiCreatedResponse({ description: 'The record has been created successfully' }) | |
@ApiBadRequestResponse({ description: 'Bad Request' }) | |
@ApiForbiddenResponse({ description: 'Forbidden' }) | |
@ApiConsumes('multipart/form-data') | |
@ApiImplicitFile({ name: 'files', required: true, description: 'File Attachments' }) | |
@UseInterceptors(FilesInterceptor('files', +process.env.MAX_FILE_COUNTS, MulterUtils.getConfig(UploadTypesEnum.ANY))) | |
@ApiBearerAuth() | |
@UseGuards(AuthGuard) | |
uploadAttachments(@AuthUser('_id') authUserId: string, @UploadedFiles() files: any[]) { | |
return this.attachmentService.addAttachments(files, authUserId); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; | |
import { existsSync, mkdirSync } from 'fs'; | |
import { diskStorage } from 'multer'; | |
import { extname } from 'path'; | |
import { v4 as uuid } from 'uuid'; | |
import { UploadTypesEnum } from '../../core/enums/upload-types.enum'; | |
/** | |
* Multer utils | |
* | |
* @export | |
* @class MulterUtils | |
*/ | |
@Injectable() | |
export class MulterUtils { | |
/** | |
* Config for allowed files | |
* | |
* @static | |
* @param {UploadTypeEnum} filesAllowed | |
* @returns | |
* @memberof MulterUtils | |
*/ | |
static getConfig(filesAllowed: UploadTypesEnum) { | |
return { | |
// Enable file size limits | |
limits: { | |
fileSize: +process.env.MAX_FILE_SIZE * 1024 * 1024, | |
}, | |
// Check the mimetypes to allow for upload | |
fileFilter: (req: any, file: any, cb: any) => { | |
if (file.mimetype.match(`/(${filesAllowed})$`)) { | |
// Allow storage of file | |
cb(null, true); | |
} else { | |
// Reject file | |
cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false); | |
} | |
}, | |
// Storage properties | |
storage: diskStorage({ | |
// Destination storage path details | |
destination: (req: any, file: any, cb: any) => { | |
const uploadPath = process.env.UPLOAD_LOCATION; | |
// Create folder if doesnt exist | |
if (!existsSync(uploadPath)) { | |
mkdirSync(uploadPath); | |
} | |
cb(null, uploadPath); | |
}, | |
// File modification details | |
filename: (req: any, file: any, cb: any) => { | |
// Calling the callback passing the random name generated with | |
// the original extension name | |
cb(null, `${uuid()}${extname(file.originalname)}`); | |
}, | |
}), | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { MulterModuleOptions, MulterOptionsFactory } from '@nestjs/platform-express/multer'; | |
/** | |
* Multer options configuration | |
* | |
* Note: Place this file inside `src/config` folder | |
* | |
* @export | |
* @class CustomMulterOptions | |
* @implements {MulterOptionsFactory} | |
*/ | |
export class CustomMulterOptions implements MulterOptionsFactory { | |
createMulterOptions(): MulterModuleOptions { | |
return { | |
dest: process.env.UPLOAD_LOCATION, | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { SetMetadata } from '@nestjs/common'; | |
// Decorator function to extract the roles data | |
export const Roles = (...roles: string[]) => SetMetadata('roles', roles); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Upload types enum | |
* | |
* @export | |
* @enum {number} | |
*/ | |
export enum UploadTypesEnum { | |
ANY = 'jpg|jpeg|png|gif|pdf|docx|doc|xlsx|xls', | |
IMAGES = 'jpg|jpeg|png|gif', | |
DOCS = 'pdf|docx|doc|xlsx|xls', | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
would u please provide how you wrote
import { AuthGuard } from './../shared/guards/auth.gaurd';
I want to know how you are able to execute the
uploadFile
in your controller after your guard?Feel free to answer my question on SO https://stackoverflow.com/questions/66311572/nest-js-pass-data-from-guard-to-uploadfile