Last active
October 17, 2023 23:11
-
-
Save jonilsonds9/efc228e34a298fa461d378f48ef67836 to your computer and use it in GitHub Desktop.
Uploading binary file (buffer) using NestJS
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
// Had to upload a binary file but multer only works with `multipart/form-data` | |
// And NestJS parses the request. So I had to manually upload it. | |
// First in `main.ts` I had to edit the following line: | |
const app = await NestFactory.create(AppModule); | |
// For: | |
const app = await NestFactory.create(AppModule, { bodyParser: false }); | |
// So NestJS allows us to handle the request. | |
// The next step is to create a Middleware, I named it `FileBufferMiddleware` | |
// I added the following content: | |
import { Injectable, NestMiddleware } from '@nestjs/common'; | |
import { raw } from 'body-parser'; | |
@Injectable() | |
export class FileBufferMiddleware implements NestMiddleware { | |
use(req: any, res: any, next: () => void): any { | |
raw({ | |
verify: (req, res, buffer) => { | |
req['fileBuffer'] = buffer; | |
}, | |
limit: '5mb', | |
})(req, res as any, next); | |
} | |
} | |
// We need to add to our `MiddlewareModule` like so: | |
export class MiddlewareModule implements NestModule { | |
configure(consumer: MiddlewareConsumer) { | |
consumer | |
.apply(FileBufferMiddleware) | |
.forRoutes({ | |
path: '/upload/:fileName', | |
method: RequestMethod.PUT, | |
}); | |
} | |
} | |
// With that we will have a `fileBuffer` which is a Buffer object in the request. | |
// And to make it even easier, I also created a decorator named `FileBuffer`: | |
import { createParamDecorator, ExecutionContext } from '@nestjs/common'; | |
export const FileBuffer = createParamDecorator( | |
(data: unknown, ctx: ExecutionContext) => { | |
const request = ctx.switchToHttp().getRequest(); | |
return request.fileBuffer || null; | |
}, | |
); | |
// So, we can just use the decorator in the Controller and we will already have the object ready to manipulate: | |
@Put('/upload/:fileName') | |
upload( | |
@Res() response: Response, | |
@Param() fileName: string, | |
@FileBuffer() fileBuffer, | |
): object { | |
if (fileBuffer === null) throw new BadRequestException('File is required'); | |
const writeStream = createWriteStream(`./data/${fileName}`); | |
writeStream.write(fileBuffer); | |
return response | |
.status(HttpStatus.CREATED) | |
.send({ HttpCode: 201, Message: 'File uploaded.' }); | |
} | |
// And that's it, now we have an upload using a binary file. |
Thanks for this.
One thing to note: for me I kept on getting the BadRequestException
until I added the following line to the raw
functions options:
type: image/jpeg
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just in case somebody wants to keep the old behavior for some routes, this a really cool article that walks you through: https://www.darraghoriordan.com/2021/06/20/parse-request-raw-body-nest-js-controller/