Skip to content

NestJS-上传管理

1、认识安装

安装依赖

👉安装 @nestjs/platform-expressmulter 库来处理文件上传

javascript

// 完整命令
nest generate module modules/upload --no-spec
nest generate controller modules/upload --no-spec
nest generate service modules/upload --no-spec

👉需要额外注意,还需要安装下面这个相关的Express库来处理文件

javascript
npm install multer @types/multer

创建上传模块和控制器

文件下我们就生成了下面这三个文件

javascript
upload.controller.ts
upload.module.ts
upload.service.ts

2、配置上传相关tsconfig.json

配置tsconfig.json

javascript
tsconfig.json中的配置types选项包含 express 和 multer 类型

{
  "compilerOptions": {
    "types": ["node", "express", "multer"]
  }
}

3、开发接口

👉upload.controller.ts

根据文件的类型我们将文件放置到不同的文件夹,同时根据时间的不同放置进入不同文件夹,都比较简单,后面我们自己慢慢扩展即可,这里实现基础的我们先

javascript
import { Controller, Post, UseInterceptors, UploadedFile } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import * as path from 'path';
import { diskStorage } from 'multer';
import { MulterModule } from '@nestjs/platform-express';

@Controller('upload')
export class UploadController {
  // 图片上传接口
  @Post('image')
  @UseInterceptors(FileInterceptor('file', {
    storage: diskStorage({
    destination: (req, file, callback) => {
      // 根据文件类型选择不同的存储目录
      const fileType = file.mimetype.split('/')[0];
      let uploadPath = '';

      if (fileType === 'image') {
        uploadPath = './uploads/images'; // 图片存放目录
      } else {
        uploadPath = './uploads/others'; // 其他文件存放目录
      }
      callback(null, uploadPath);
    },
    filename: (req, file, callback) => {
      // 重命名文件,防止文件名重复
      const filename = `${Date.now()}-${file.originalname}`;
      callback(null, filename);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 }, // 限制上传文件大小为 5MB
}))

uploadImage(@UploadedFile() file: Express.Multer.File) {
  if (!file) {
    throw new Error('No file uploaded!');
  }
  return { message: 'File uploaded successfully', filePath: path.join('uploads/images', file.filename) };
}

然后把操作抽离到upload.service.ts即可

4、测试接口

👉检查图片接口

检测一下我们的接口,这个时候给我们返回的提示

javascript
{
    "message": "File uploaded successfully",
    "filePath": "uploads\\images\\1746671596199-Nexusapp.jpg"
}

查看我们的文件以后我们呢会发现,根目录下面已经增加成功了文件夹以及里面的文件夹

javascript
├─uploads
├──files
└──images
└────────xxx.jpg //这个就是我们刚放上去的文件

👉完善返回路径

把上面的file输出以后我们可以发现file内容是下面这样子的,完善返回我们就可以直接查看地址访问图片

javascript
{
  fieldname: 'file',
  originalname: 'nexusvue-dicttype.png',
  encoding: '7bit',
  mimetype: 'image/png',
  destination: './uploads/images',
  filename: '1746672366720-nexusvue-dicttype.png',
  path: 'uploads\\images\\1746672366720-nexusvue-dicttype.png',
  size: 88547
}

从里面拿到我们想要的接口信息以及其他的路径相关的信息,然后拼出路径地址

javascript

//完整的本地图片路径
localhost:8888/uploads/images/1746674928131-Nexusapp.jpg


 return { 
    message: '上传成功', 
    code: 200,
    imgpath: `${CONFIG.API_HTTP}://${CONFIG.API_IP}:${CONFIG.API_PORT}/${uploadPath}/${file.filename}`,
    imgurl:`/${uploadPath}/${file.filename}`,
    size: file.size,
    fileName: '图片-'+file.filename,
  };

5、配置静态路径

👉step1

刚刚开始我们配置的静态路径是这样子的

javascript
// 配置静态文件服务
   app.useStaticAssets(join(__dirname, '..', 'uploads'), {
    prefix: '/uploads/',  // 配置访问路径
  });

这里直接报错

javascript
// 配置静态文件服务
 app.useStaticAssets(join(__dirname, '..', 'uploads'), {
  prefix: '/uploads/',  // 配置访问路径
});

👉step2

后来我们配置成这样子,准备使用express的,结果无效(一顿操作猛如虎)

javascript
import * as express from 'express';

// 配置静态文件服务
  app.use(express.static(join(__dirname, '..', 'uploads'), {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  lastModified: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now().toString());
  },
}));

👉step3

安装插件依赖,说是应该通过导入 ServeStaticModule 并在 AppModule 中进行配置

javascript
npm install @nestjs/serve-static

👉修改 app.module.ts

javascript
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    // 配置 ServeStaticModule
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'uploads'),  // 静态文件目录
      serveRoot: '/uploads/',  // 配置访问路径前缀
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

ok,总算可以了,所以不同版本确实踩坑才能知道

Released under the MIT License.