写这个是记录一下在Fastify
底层写上传的方式,因为默认Nest
的底层是Express
,
Nest文档中对Express和Fastify的解释以及如何切换Fastify!
在Nest文档中也有提到上传,不过默认是适用于Express
。
express-multer模块上传方式。
如果是用Fastify
最简单方式就是使用fastify官方提供的包fastify/multipart
。
fastify-multipart(github)地址
更详细的说明可以看Github
一、安装
安装还是老三样 npm
Yarn
pnpm
我是用的pnpm
tem
pnpm i @fastify/multipart
二、注册插件
注册在入口文件main.ts
里面
通过fastify
注册方法register
typescript
import multipart from '@fastify/multipart';
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
{ cors: true },
);
// 如下注册
await app.register(multipart, {
// 注册参数,Infinity就是无限大,
// 不写fileSize和files的话 默认是10MB和最大上传一个文件
limits: {
fileSize: Infinity, // For multipart forms, the max file size in byt
files: Infinity, // Max number of file fields
fieldNameSize: 100, // Max field name size in bytes
fieldSize: 100, // Max field value size in bytes
fields: 10, // Max number of non-file fields
headerPairs: 2000, // Max number of header key=>value pairs
parts: 1000 // For multipart forms, the max number of parts
},
});
注册完以后就可以去server层使用了,具体更多的使用方法可以参考fastify-multipart
三、使用
先在controller
层写上传方法
typescript
// 引用类型
import type { FastifyRequest, FastifyReply } from 'fastify';
import { Request, Response } from '@nestjs/common';
@Post('uploadFile')
async uploadFile(
@Request() request: FastifyRequest,
@Response() response: FastifyReply,
) {
return await this.loadFileService.uploadFile(request, response);
}
实现完Controller
当然开始写Service
层了
typescript
import * as fs from 'fs';
async uploadFile(request: FastifyRequest, response: FastifyReply) {
// 这个file就是上传的流文件,request里面还有个files是文件流数组
const file = await request.file();
// 拿到文件流就随便玩啦!
// 下面就是我自己对file做的操作,也可以上传到Oss,或者其他地方。
const config = await this.yamlConfigService.getUploadConfig();
if (config) {
// 调用node的fs模块,创建写入流,这里的地址是我拼接写入的地方,
const writeStream = fs.createWriteStream(
`${config.uploadPosition}${file.filename}`,
);
//通过pipe写入,
file.file.pipe(writeStream);
// 监听写入流的错误
writeStream.once('error', (e) => {
console.error(e);
// 出现错误就接口返回500给前台。
response
.code(HttpStatus.SERVICE_UNAVAILABLE)
.send(
responseError(
'上传失败,请稍后尝试!',
HttpStatus.SERVICE_UNAVAILABLE,
),
);
});
// 监听写入流完成事件
writeStream.once('finish', () => {
const result = {
url: `${config.endpoint}/${file.filename}`,
name: file.filename,
};
// 通过response 返回给接口数据。
response.code(HttpStatus.OK).send(responseSuccess(result));
});
// 当然也要执行end事件,去做后续清理,手动释放内存啦!
writeStream.once('end', async () => {
writeStream.removeAllListeners();
await request.cleanRequestFiles();
writeStream.close();
});
writeStream.end();
}
}
}
四、注意问题
当要取除文件外的其他字段值需要特别注意
注意:按顺序(流)使用多部分。因此,表单字段的顺序对于如何data.fields向您显示字段非常重要。我们建议您将值字段放在任何文件字段之前。这将确保您的字段在开始使用任何文件之前可访问。如果您无法控制放置字段的顺序,请务必在使用流之后读取,否则它将仅包含当时解析的字段。
TypeScript
const files = request.files();
const fileParams = await files.next();
const { ... } = fileParams.value.fields //这里面就是要取的其他字段
//当然你如果直接要取文件跟第三步一样,但是取不到其他字段
const file = request.file();
五、总结
在使用fastify/multipart
包确实是一个不错的上传选择方案。
极大简化了fastify底层的使用成本。
文章最后更新于 2024-12-22 23:36
评论一下吧!
F
😀
Dream2024-11-09
🙃
F
回复 @Dream
66666