前言
本章节主要介绍nestjs
服务端上传图片资源使用express中间件 multer
,FileInterceptor,并通过express static
生成静态目录暴露出图片资源地址,前端通过postman上传图片资源
项目目录结构
大致项目结构如下: src/upload
为上传资源模块,根目录下uploads
为上传资源存放位置
css
nest-upload/
├── src/
│ ├── upload/ (处理上传资源模块)
│ │ ├── upload.controller.ts
│ │ ├── upload.module.ts
│ ├── app.module.ts
│ ├── main.ts
├── uploads/ (上传的文件将会存储在这里)
├── .gitignore
├── package.json
├── tsconfig.json
└── README.md
demo最终效果: Postman图片上传和访问
1. 快速创建nestjs 项目
这里通过nestjs CLI
快速创建项目nest-upload
,点击查看如何创建项目
shell
nest new nest-upload
cd nest-upload
创建成功后切换到项目内,由于nestjs
基于 Express 框架构建,所以Express
包已经自带不需要安装,其中multer
,@types/multer
依赖包需要安装
shell
npm i multer @types/multer --save
再通过nestjs CLI
快速创建 upload
资源上传模块
shell
nest g mo upload # 创建模块
nest g co upload --no-spec # 创建controller层
2. multer资源上传处理
图片资源上传后服务需要把资源存储到根目录下的uploads
中,需要对启动文件 src/main.ts
判断是否有uploads
目录,当没有uploads
时候会自动创建
diff
// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
+import { join } from 'path';
+import { existsSync, mkdirSync } from 'fs';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
+ const uploadDir = join(process.cwd(), 'uploads');
+ if (!existsSync(uploadDir)) {
+ mkdirSync(uploadDir);
+ }
await app.listen(3000);
}
bootstrap();
upload.module.ts
添加处理上传资源代码:
ts
// src/upload/upload.module.ts
import { Module } from '@nestjs/common';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname, join } from 'path';
import { UploadController } from './upload.controller';
import { UploadService } from './upload.service';
// 获取项目根目录并设置上传目录
const uploadDir = join(process.cwd(), 'uploads');
@Module({
imports: [
MulterModule.register({
storage: diskStorage({
destination: (req, file, cb) => {
cb(null, uploadDir);
},
filename: (req, file, cb) => {
const ext = extname(file.originalname);
const filename = `${Date.now()}${ext}`;
cb(null, filename);
},
}),
fileFilter: (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(new Error('Only images are allowed...'), false);
}
},
}),
],
controllers: [UploadController],
providers: [UploadService],
})
export class UploadModule { }
其中 fileFilter
可以控制上传文件的类型,大小等
现在在upload.controller.ts
创建上传图片接口: localhost:3000/upload/uploadImage
请求方式为Post
, Post body
中参数为file
ts
// src/upload/upload.controller.ts
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
@Controller('upload')
export class UploadController {
@Post('/uploadImage')
@UseInterceptors(FileInterceptor('file'))
async uploadImage(@UploadedFile() file) {
return "upload success"
}
}
其中@FileInterceptor
,@UploadedFile
为nestjs
框架提供的上传资源装饰器(查看文档)
3.Postman上传图片
首先需要安装Postman
(资源下载),后创建上传图片资源请求,步骤:
之后点击 Select Files
选择上传的图片,点击Send
按钮上传图片,效果:
上方为nest-upload
项目根目录下资源存放文件uploads
生成上传图片资源情况
4. 生成静态资源目录
日常开发中,当资源上传成功后需要返回可访问资源的url地址,这里我们需要修改src/main.ts
通过express static
生成静态资源目录
diff
// src/main.ts
import { NestFactory } from '@nestjs/core';
+ import * as express from 'express';
...
async function bootstrap() {
...
+ app.use('/uploads', express.static(join(process.cwd(), 'uploads')));
await app.listen(3000);
}
bootstrap();
修改upload.controller.ts
图片上传成功后返回对应资源的url地址
diff
// src/upload/upload.controller.ts
...
async uploadImage(@UploadedFile() file) {
- return "upload success"
+ const fileUrl = `http://localhost:3000/uploads/${file.filename}`;
+ return {
+ url: fileUrl,
+ };
}
}
再次使用Postman
上传图片资源效果:
总结
资源上传为大部分应用都需要有的需求,nestjs
通过FileInterceptor
,UploadedFile
生态支持上传资源,再通过express
静态生成目录暴露出资源地址。nestjs
是在express
基础上封装的框架,所以项目中可以不需要安装express
包依赖,直接使用express