Installation
npm install fastify-file-interceptor
yarn add fastify-file-interceptor
FileFastifyInterceptor() may not be compatible with third party cloud providers like Google Firebase or others.
This package is base on NestJs ,fastify-multer
import "reflect-metadata";
import {
FastifyAdapter,
NestFastifyApplication,
} from "@nestjs/platform-fastify";
import { join } from "path";
import { contentParser, MulterFile } from "fastify-file-interceptor";
async function bootstrap(): Promise<void> {
const app =
(await NestFactory.create) <
NestFastifyApplication >
(AppModule, new FastifyAdapter());
await app.listen(3000);
app.register(contentParser);
app.useStaticAsset({ root: join(__dirname, "../../example") });
}
bootstrap();
import {
Body,
Controller,
Post,
UploadedFile,
UploadedFiles,
UseInterceptors,
} from "@nestjs/common";
import { ApiConsumes, ApiTags } from "@nestjs/swagger";
import { diskStorage } from "multer";
import { AppService } from "./app.service";
import {
MultipleFileDto,
SingleFileDto,
AnyFileDto,
FieldsFileDto,
} from "./dto/re-export-dto";
import { editFileName, imageFileFilter } from "./utils/file-upload-util";
import {
AnyFilesFastifyInterceptor,
FileFastifyInterceptor,
FileFieldsFastifyInterceptor,
FilesFastifyInterceptor,
} from "fastify-file-interceptor";
@Controller()
@ApiTags("Upload File ")
export class AppController {
constructor(private readonly appService: AppService) {}
@ApiConsumes("multipart/form-data")
@Post("single-file")
@UseInterceptors(
FileFastifyInterceptor("photo_url", {
storage: diskStorage({
destination: "./upload/single",
filename: editFileName,
}),
fileFilter: imageFileFilter,
})
)
single(@UploadedFile() file: MulterFile, @Body() body: SingleFileDto) {
console.log({ ...body, photo_url: file });
return { ...body, photo_url: file };
}
@ApiConsumes("multipart/form-data")
@Post("multiple-file")
@UseInterceptors(
FilesFastifyInterceptor("photo_url", 10, {
storage: diskStorage({
destination: "./upload/multiple",
filename: editFileName,
}),
fileFilter: imageFileFilter,
})
)
multiple(
@UploadedFiles() files: MulterFile[],
@Body() body: MultipleFileDto
) {
console.log({ ...body, photo_url: files });
return { ...body, photo_url: files };
}
@ApiConsumes("multipart/form-data")
@Post("any-file")
@UseInterceptors(
AnyFilesFastifyInterceptor({
storage: diskStorage({
destination: "./upload/any",
filename: editFileName,
}),
fileFilter: imageFileFilter,
})
)
anyFile(@UploadedFiles() files: MulterFile, @Body() body: AnyFileDto) {
console.log({ ...body, photo_url: files });
return { ...body, photo_url: files };
}
@ApiConsumes("multipart/form-data")
@Post("fields-file")
@UseInterceptors(
FileFieldsFastifyInterceptor(
[
{
name: "photo_url",
maxCount: 10,
},
{
name: "images",
maxCount: 10,
},
],
{
storage: diskStorage({
destination: "./upload/fields",
filename: editFileName,
}),
fileFilter: imageFileFilter,
}
)
)
fields(@UploadedFiles() { photo_url, images }, @Body() body: FieldsFileDto) {
console.log({ ...body, photo_url, images });
return { ...body, photo_url, images };
}
}
NOTE property destination inside diskStorage is the location in our project directory where we want to store the image
file-upload-util.ts
import { Request } from "express";
import { extname } from "path";
export const editFileName = (req: Request, file: MulterFile, callback) => {
const name = file.originalname.split(".")[0];
const fileExtName = extname(file.originalname);
callback(null, `${name}${fileExtName}`);
};
export const imageFileFilter = (req: Request, file: MulterFile, callback) => {
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return callback(new Error("Only image files are allowed!"), false);
}
callback(null, true);
};
Hint
save image as CDN and display in browser
import { FastifyRequest } from "fastify";
interface FileMapper {
file: Express.Multer.File;
req: FastifyRequest;
}
interface FilesMapper {
files: Express.Multer.File[];
req: FastifyRequest;
}
export const fileMapper = ({ file, req }: FileMapper) => {
const image_url = `${req.protocol}://${req.headers.host}/${file.path}`;
return {
originalname: file.originalname,
filename: file.filename,
image_url,
};
};
export const filesMapper = ({ files, req }: FilesMapper) => {
return files.map((file) => {
const image_url = `${req.protocol}://${req.headers.host}/${file.path}`;
return {
originalname: file.originalname,
filename: file.filename,
image_url,
};
});
};
Usage
if you already know how to use function from "@nestjs/platform-express" it's the same.
"fastify-file-interceptor";
import {
AnyFilesFastifyInterceptor,
FileFastifyInterceptor,
FileFieldsFastifyInterceptor,
FilesFastifyInterceptor,
} from "fastify-file-interceptor";
"@nestjs/platform-express";
import {
AnyFilesInterceptor,
FileFieldsInterceptor,
FileInterceptor,
FilesInterceptor,
} from "@nestjs/platform-express";
You can install example test on swagger
Example Repo on github: https://github.com/chanphiromsok/example-fastify-file-interceptor