NestJS文件上传之本地存储、腾讯Cos存储
此文章将介绍在
NestJs
中如何接受上传的文件,包括本地和腾讯的Cos云存储。
本地图片存储
本地存储图片,需要打开静态资源目录访问。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
async function bootstrap() {
// 添加NestExpressApplication泛型,扩展属性的类型推导。
// 不然eslint会报错useStaticAssets不存在。
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// 配置允许跨域
app.enableCors();
// 使用静态目录。项目的public文件夹下的所有文件都可以直接访问
app.useStaticAssets(join(__dirname, '..', 'public'));
await app.listen(3000);
}
bootstrap();
前期准备
-
引入相关依赖
pnpm i multer --save pnpm i @types/multer -D
-
生成上传模块
nest res g upload
代码实现
-
upload.module
在这个文件中导入并注册
multer
模块。import { Module } from '@nestjs/common'; import { UploadService } from './upload.service'; import { UploadController } from './upload.controller'; import { MulterModule } from '@nestjs/platform-express'; import * as multer from 'multer'; import { join } from 'path'; @Module({ imports: [ MulterModule.register({ storage: multer.diskStorage({ destination: (req, file, cb) => { // 上传文件的目录 保证项目根目录中public/uploads文件夹存在 cb(null, join(__dirname, '../..', 'public/uploads')); }, filename: (req, file, cb) => { // 上传文件的文件名称 cb(null, `${Date.now()}-${file.originalname}`); }, }), }), ], controllers: [UploadController], providers: [UploadService], }) export class UploadModule {}
-
upload.controller
这个接口只需要几个装饰器就可以了,当文件上传时,会自动将文件保存至
public/uploads
文件夹下import { Controller, Post, UseInterceptors, UploadedFile } from '@nestjs/common'; import { UploadService } from './upload.service'; import { FileInterceptor } from '@nestjs/platform-express'; @Controller('upload') export class UploadController { constructor(private readonly uploadService: UploadService) {} @Post() @UseInterceptors(FileInterceptor('file')) create(@UploadedFile() file) { console.log(file); } }
腾讯Cos云存储
使用第三方平台进行云存储,第一步要干嘛?当然是去腾讯白嫖六个月的免费云存储了🤭。
注意:每日请求
超过一万次
是需要计入流量费用的。
前期准备
-
引入相关依赖
pnpm i cos-nodejs-sdk-v5 --save
-
生成上传模块
nest res g upload
代码实现
-
upload.module
import { Module } from '@nestjs/common'; import { UploadService } from './upload.service'; import { UploadController } from './upload.controller'; @Module({ controllers: [UploadController], providers: [UploadService], }) export class UploadModule {}
-
upload.controller
import { Controller, Post, UseInterceptors, UploadedFile } from '@nestjs/common'; import { UploadService } from './upload.service'; import { FileInterceptor } from '@nestjs/platform-express'; @Controller('upload') export class UploadController { constructor(private readonly uploadService: UploadService) {} @Post() @UseInterceptors(FileInterceptor('file')) async create(@UploadedFile() file) { return await this.uploadService.create(file); } }
-
upload.service
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import * as COS from 'cos-nodejs-sdk-v5'; @Injectable() export class uploadService { private readonly cos: COS = new COS({ SecretId: process.env.COS_SECRET_ID, // 密钥Id SecretKey: process.env.COS_SECRET_KEY // 密钥Key }); private readonly bucket: string = 'blog-1307950541'; private readonly region: string = 'ap-nanjing'; private readonly baseParams: COS.PutObjectParams = { Bucket: this.bucket, // 桶名称 Region: this.region, // 桶的所属地域 Body: undefined, // 上传的文件二进制流 Key: '' // 文件在桶中的存储path,以及存储名称 }; constructor() {} // 新增 async create(file) { const params = Object.assign(this.baseParams, { Body: file.buffer, Key: `/image/${Date.now()}-${file.originalname}` }); try { // 视频上传 if (file.mimetype.includes('video')) { params.Key = '/video/' + Date.now() + '-' + file.originalname; } // 音频上传 if (file.mimetype.includes('audio')) { params.Key = '/audio/' + Date.now() + '-' + file.originalname; } const res = await this.cos.putObject(params); return res.Location; } catch (error) { await this.remove(params.Key); throw new HttpException('文件上传失败', HttpStatus.BAD_REQUEST); } } // 删除 async remove(key: string) { const params = Object.assign(this.baseParams, { Key: key }); const res = await this.cos.deleteObject(params); return res; } }