Email on Acid Upload Images File Name Is Invalid
NestJS File Uploading Using Multer
How to develop a uncomplicated file-uploading app
This guide will prove you how yous tin can implement file uploading into your NestJS application and the things you should keep in heed when doing and then. You lot will develop an awarding with iii endpoints that will practise the following:
Function-1 upload paradigm to a server Directory
- Upload an image;
- Upload multiple images;
- Get the paradigm using the image path.
function-two procedure uploaded stream without storing
- Upload an epitome;
- Upload multiple images;
- Get the epitome using the image path.
You will besides add custom utilities to edit the file proper noun and validate the file upload for images.
So without wasting whatsoever farther time, allow's get into information technology.
Setup - Part-1 upload image to a server Directory
The first thing you demand to exercise is create a NestJS project that will hold our fileserver. For that, you need to open your terminal and run the following control:
nest new nest-file-uploading && cd nest-file-uploading
This creates a new directory called nest-file-uploading and initializes it with a standard NestJS configuration.
With the directory in place, you can go alee and install the needed dependencies for the application using the post-obit commands:
npm install @nestjs/platform-limited --save npm install @types/limited -D
The last thing you lot need to practise before jumping into coding is create the files and folders needed for the project. This is very simple because the awarding just needs one more file.
mkdir src/utils touch src/utils/file-uploading.utils.ts
To first the app, you can now execute npm run start:dev in your last.
Uploading Files
Now that you take completed the setup process, you can go ahead and beginning implementing the actual functionality. Let'south get-go by importing the MulterModule in your AppModule and then you can use Multer in your other files.
import { Module } from '@nestjs/common' ; import { AppController } from './app.controller' ; import { MulterModule } from '@nestjs/platform-limited' ; @Module ( { imports: [MulterModule. register ( { dest: './files' , } ) ] , controllers: [AppController] , } ) consign class AppModule { }
Here you lot import the MulterModule from @nestjs/platform-express and add together information technology to your imports statement. You likewise define the destination in which the files volition exist saved when an upload occurs.
Note: This destination starts at the root path of the project, not the src folder.
The next footstep is to implement the bodily uploading functionality, which is rather simple. You simply need to add together a FileInterceptor() to a normal mail service request handler and then pull out the file from the request using the @UploadedFile() decorator.
@Post ( ) @UseInterceptors ( FileInterceptor ( 'epitome' ) , ) async uploadedFile ( @UploadedFile ( ) file ) { const response = { originalname: file.originalname, filename: file.filename, } ; return response; }
The FileInterceptor takes ii arguments: a fieldName and an optional options object, which you volition apply later to bank check for the correct file types and give the file a custom name in the directory.
Uploading multiple files at once is about the same; you just demand to utilize the FilesInterceptor instead and laissez passer an actress argument of the maximum number of files.
@Mail service ( 'multiple' ) @UseInterceptors ( FilesInterceptor ( 'image' , 20 , { storage: diskStorage ( { destination: './files' , filename: editFileName, } ) , fileFilter: imageFileFilter, } ) , ) async uploadMultipleFiles ( @UploadedFiles ( ) files ) { const response = [ ] ; files. forEach ( file => { const fileReponse = { originalname: file.originalname, filename: file.filename, } ; response. push (fileReponse) ; } ) ; return response; }
That was uncomplicated. The only problem here is that the user can upload every file type regardless of the file extension, which doesn't suit all projects and that the file proper name is just some random number.
Allow's fix that past implementing some utilities in your file-upload.utils.ts file.
First, permit'southward implement a file blazon filter that but allows images to exist uploaded.
export const imageFileFilter = ( req, file, callback ) => { if ( !file.originalname. match ( /\.(jpg|jpeg|png|gif)$/ ) ) { render callback ( new Error ( 'Merely image files are allowed!' ) , false ) ; } callback ( null , true ) ; } ; export const editFileName = ( req, file, callback ) => { const name = file.originalname. divide ( '.' ) [ 0 ] ; const fileExtName = extname (file.originalname) ; const randomName = Assortment ( 4 ) . fill up ( nil ) . map ( ( ) => Math. circular (Math. random ( ) * xvi ) . toString ( 16 ) ) . join ( '' ) ; callback ( aught , ` ${proper name} - ${randomName} ${fileExtName} ` ) ; } ;
Hither yous create a middleware function, which checks if the file type is an image. If so it returns truthful, and the image will be uploaded. If not, you throw an mistake and return fake for the callback.
The editFileName* *function has the aforementioned structure just creates a custom filename using the original proper name, the file extension, and four random numbers.
Now that you have created these two middleware functions, it's time to use them in your app.controller.ts file. For that you lot just need to add together an extra configuration object to the FileInterceptor, which then looks similar this:
@Post ( ) @UseInterceptors ( FileInterceptor ( 'image' , { storage: diskStorage ( { destination: './files' , filename: editFileName, } ) , fileFilter: imageFileFilter, } ) , ) async uploadedFile ( @UploadedFile ( ) file ) { const response = { originalname: file.originalname, filename: file.filename, } ; return response; } @Post ( 'multiple' ) @UseInterceptors ( FilesInterceptor ( 'paradigm' , 20 , { storage: diskStorage ( { destination: './files' , filename: editFileName, } ) , fileFilter: imageFileFilter, } ) , ) async uploadMultipleFiles ( @UploadedFiles ( ) files ) { const response = [ ] ; files. forEach ( file => { const fileReponse = { originalname: file.originalname, filename: file.filename, } ; response. button (fileReponse) ; } ) ; return response; }
Lastly you will add a get road, which will accept the epitome path as an argument and return the prototype using the sendFile method.
@Get ( ':imgpath' ) seeUploadedFile (@Param ( 'imgpath' ) prototype, @Res ( ) res) { return res. sendFile (prototype, { root: './files' } ) ; }
Testing the Application
Now that you accept finished your application, it'due south time to test it by sending an HTTP request to your endpoint. This can be done using the curlicue command in the final or by using an HTTP client software like Postman or Insomnia. I personally utilise Indisposition, but information technology should be well-nigh the same in Postman.
Beginning the server using the following command:
Every bit indicated by the terminal output, the server is at present running on http://localhost:3000. To exam the API you now only need to create a new HTTP request and change the request torso to multipart and so you can upload files.
role-2 process uploaded stream without storing
In this procedure where we merely need to upload and file and process on the fly and so we can utilize this On this instance we would not need mutler storage on server side so we don't demand MulterModule.annals
anywhere in our code
Similar we will just upload and convert uploaded file to stream and procedure information technology without uploading or storing it on server
Lets write controller router for this
export const imageFileFilter = ( req:whatever, file:whatsoever, callback:any ) => { if ( !file.originalname. match ( /\.(csv)$/ ) ) { return callback ( new Error ( 'But csv files are allowed!' ) , false ) ; } callback ( null , truthful ) ; } ; @Controller ( '/api/v1/test/upload' ) @ApiBearerAuth ( 'dominance' ) @UsePipes ( new ValidationPipe ( { whitelist: true , transform: true , } ) ) export grade UploadSupplierController { constructor ( private readonly userSupplierProfileService: UserSupplierProfileService, ) { } @HttpCode (HttpStatus. OK ) @ApiOkResponse ( { clarification: RESULTS_RETURNED } ) @ApiBadRequestResponse ( { description: PARAMETERS_FAILED_VALIDATION } ) @ApiTags ( 'examination' ) @ApiConsumes ( 'multipart/form-data' ) @uploadFile ( 'filename' ) @Mail service ( '/' ) @UseInterceptors ( FileInterceptor ( 'filename' , { fileFilter: imageFileFilter, } ) , ) async uploadedFile ( @UploadedFile ( ) file: whatsoever, @Query ( ) params: UserSupplierParam, @User ( ) userId: string, ) { try { if ( !file) { throw new BadRequestException ( 'invalid file provided, immune *.csv single file' ) ; } const readStream = getStream (file.buffer) ; await this .service. create (readStream, params.id, userId) ; return {success: true } } grab (err) { throw err; } } }
This controller can exist used to upload single file or multiple files, NestJS provided @annotations to manage all these things, We merely need to alter uploadFile to uploadFiles.
@ApiConsumes ( 'multipart/form-data' ) @uploadFiles ( 'filename' ) @Post ( '/' ) @UseInterceptors ( FileInterceptor ( 'filename' , { fileFilter: imageFileFilter, } ) , ) async uploadedFiles ( @UploadedFiles ( ) file: any, @Query ( ) params: UserSupplierParam, @User ( ) userId: string, ) { try { if ( !file) { throw new BadRequestException ( 'invalid file provided, immune *.csv unmarried file' ) ; } const readStream = getStream (file.buffer) ; look this .service. create (readStream, params.id, userId) ; return {success: true } } catch (err) { throw err; } } }
We can read uploaded unmarried file stream or multiple file using buffer conversion to stream Now nosotros can uploads file and if file is not valid then nosotros tin throw exception for bad request
const getStream = require ( 'into-stream' ) ; async uploadedFile ( @UploadedFile ( ) file: any, @Query ( ) params: UserSupplierParam, @User ( ) userId: string, ) { endeavor { if ( !file) { throw new BadRequestException ( 'invalid file provided, allowed *.csv single file' ) ; } const readStream = getStream (file.buffer) ; look this .service. create (readStream, params.id, userId) ; return {success: truthful } } catch (err) { throw err; } }
This is all we demand to setup file upload with or without server directory based upload, NestJS provided these cool @UploadFile annotations which actually helps to manage things like mutler equally its written on top of mutler, Nosotros can also pass mutler options while uploading
@Post ( ) @UseInterceptors ( FileInterceptor ( 'image' , { storage: diskStorage ( { destination: './files' , filename: editFileName, } ) , fileFilter: imageFileFilter, } ) , )
If yous have any questions or feedback, permit me know.
Source: https://tkssharma.com/file-upload-feature-using-nestjs/
0 Response to "Email on Acid Upload Images File Name Is Invalid"
Postar um comentário