浅浅记录一下Nestjs上传 这几天也研究了mysql ngnix minio 这些服务器里面的东西
本地磁盘上传
- 首先创建模块
- 注册表
- 编写module 导入需要的插件
- 编写controll
- 编写service 并上传到表里面
创建模块
下载依赖
npm i @type/multer dayjs multer @nestjs/platform-express
创建文件夹
模块里面的内容
import { Module } from '@nestjs/common';
import { FileController } from './file.controller';
import * as dayjs from 'dayjs';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { FileEntity } from './file.entity';
import { FileService } from './file.service';
@Module({
controllers: [FileController],
imports: [TypeOrmModule.forFeature([FileEntity]),
MulterModule.register({
// storage: diskStorage({
// //设置上传文件的路径
// destination: `./public/uploads/${dayjs().format('YYYY-MM-DD')}`,
// filename: (req, file, cb) => {
// //文件上传之后的回调,文件为空不走
// //取出结尾的类型为扩展名
// let ext = file.originalname.split('.').at(-1)
// // 在此处自定义保存后的文件名称,仍然使用原后缀名,没有就不用
// let filename = `${new Date().getTime()}.${ext ? ext : ''}`
// return cb(null, filename)
// },
// }),
}),
],
providers: [FileService]
})
export class FileModule {
}
如果你需要上传到磁盘就打开注释 直接上传到minio就不需要
注册表
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
//文件表 后续弄远程url
@Entity('file')
export class FileEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
originalname :string
@Column()
mimetype:string
@Column()
size:number
@Column({ type: 'varchar', length: 500 })
path:string
}
因为上传到minio字符太长了就改成了这个类型
Controller层
使用Express.Multer.File处理文件类型
export class FileController {
constructor(private fileService: FileService) { }
@Post('/upload')
@UseInterceptors(FileInterceptor('file'))
upload(@UploadedFile() file: Express.Multer.File) {
//单上传到磁盘
return wrapperResponse(
this.fileService.uploadFile(file),
'上传文件成功'
)
}
}
service层
拿到上传的文件并放入数据库
import { Injectable } from '@nestjs/common';
import { HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { FileEntity } from './file.entity'; // 你的文件实体
import { minioClient } from './minio';
import { join } from 'path';
import { existsSync, unlink, unlinkSync } from 'fs';
@Injectable()
export class FileService {
constructor(
@InjectRepository(FileEntity)
private readonly fileRepository: Repository<FileEntity>,
) { }
uploadFile(mfile: Express.Multer.File): Promise<FileEntity> {
console.log(mfile);
if (!mfile) {``
throw new HttpException('文件不存在', HttpStatus.BAD_REQUEST);
}
// 创建文件实体
const fileEntity = new FileEntity();
fileEntity.originalname = mfile.originalname;
fileEntity.mimetype = mfile.mimetype;
fileEntity.size = mfile.size;
fileEntity.path = mfile.path;
// 保存到数据库
return this.fileRepository.save(fileEntity);
}
}
但是要想访问到 需要在我们的main.ts配置
app.use('/public', express.static(`${__dirname}/../public`));
即可访问到
上传minio
上传到磁盘并且上传到minio
准备工作
首先需要在你服务器上下载minio 并且启动服务
然后进入到这个页面
可以先创建一个buchets 我这里叫nest
在这里申请你的acesskey 并且记录下来我们一会会用
配置minio
按理说文件应该放在.env中 但是我还没写
配置如下 需要配置IP地址并且配置你之前申请的acesskey
Service层处理
导入这个minioClient 写入几个方法 putFile 和putFileBuffer 均为推送到minio
putFile(filename, path) {
console.log(filename, path);
return minioClient.fPutObject('nest', filename,
path)
}
putFilebuffer(filename: string, buffer: Buffer) {
//如果想两个端都存在文件,可以使用 fPutObject 逻辑更简单
return minioClient.putObject(
'nest',
filename,
buffer
)
}
//获取url签名
presUrl(filename: string) {
return minioClient.presignedUrl(
'GET',
'nest',
filename,
)
}
单上传到minio
单上传到minio并且返回一个url代码如下
async uploadMinio(mfile: Express.Multer.File) {
console.log(mfile);
if (!mfile) {
throw new HttpException('文件不存在', HttpStatus.BAD_REQUEST);
}
// 确保 originalname 是字符串
const { originalname } = mfile;
if (typeof originalname !== 'string') {
throw new HttpException('文件名无效', HttpStatus.BAD_REQUEST);
}
// 生成文件扩展名
let ext = originalname.split('.').at(-1);
let filename = `${new Date().getTime()}.${ext ? ext : ''}`;
try {
if (!Buffer.isBuffer(mfile.buffer)) {
throw new HttpException('文件数据无效', HttpStatus.BAD_REQUEST);
}
await this.putFilebuffer(filename, mfile.buffer);
let url = await this.presUrl(filename);
console.log(url);
return { url };
} catch (e) {
throw new HttpException('上传失败', HttpStatus.BAD_REQUEST);
}
}
上传到磁盘又上传到服务器
//即上传到服务器也上传到磁盘
async uploadFileMinio(mfile: Express.Multer.File) {
if (!mfile) {
throw new HttpException('文件不存在', HttpStatus.BAD_REQUEST);
}
let url = null
const linkPath = join(__dirname, `../../${mfile.path}`)
try {
await this.putFile(mfile.filename, mfile.path)
url = await this.presUrl(mfile.filename)
} catch (e) {
existsSync(linkPath) && unlinkSync(linkPath)
throw new HttpException('上传失败', HttpStatus.BAD_REQUEST);
}
existsSync(linkPath) && unlinkSync(linkPath)
return { url }
}
无非是上传path和buffer的区别但是不知道为啥删除磁盘的文件有问题路径是有的 但是一直报错找不到目录 不知道是为啥 希望大佬解答
formdata
async generatePresignedPostPolicy(filename: string) {
const policy = new PostPolicy();
policy.setBucket(this.MINIO_BUCKETNAME);
policy.setContentType('multipart/form-data');
policy.setKey(filename);
policy.setContentLengthRange(1, 5 * 1024 * 1024 * 1024); // 5G
return this.client.presignedPostPolicy(policy);
}
可以添加这段代码去实现多个参数的情况
总结
之前nestjs因为顾虑太多然后一直没有正式的学 不过现在快学完了 还有连表查询和过滤器统一响应处理基本就没了…