用NestJS和MySQL处理文件上传
许多开发者都鄙视处理文件上传。在这篇博客中,我们将教你如何使用NestJS和MySQL建立一个文件上传功能。
许多开发者都不喜欢处理文件上传的问题。这可能是由于缺乏关于采取最佳方法的知识,或者难以确定如何配置他们的NestJS应用程序来处理文件上传。许多人可能想把文件直接保存到MySQL数据库中,或保存图像名称并让图像保存在磁盘存储中:这一切都取决于他们的喜好和他们想要实现的目标。本教程将教你如何使用NestJS和MySQL建立一个文件上传功能。
前提条件
在你开始学习本教程之前,请确保你的系统满足以下要求。
设置NestJS
一旦满足上述要求,继续安装NestJS CLI,并通过运行以下命令创建一个新项目。
Shell
$ npm i -g @nestjs/cli $ nest new file-upload
这些命令将安装NestJS CLI并创建一个新的NestJS项目,其文件夹结构如下。
在NestJS项目创建完成后,继续下一步--通过运行以下命令为你的应用程序安装所需的依赖。
Shell
npm install --save @nestjs/typeorm typeorm mysql2
在上述命令中,你已经安装了TypeORM和mysql2模块:它们将使你的应用程序连接到MySQL数据库并对其进行操作。
设置MySQL数据库
在安装了上述依赖项后,继续设置并连接到你的MySQL数据库。要开始,在app.module.ts 文件中添加下面的代码片段:
TypeScript
...
import { TypeOrmModule } from '@nestjs/typeorm';
import { Image } from './image.entity';
@Module({
imports: [TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: '1234',
database: 'blog',
entities: [Image],
synchronize: true,
}),
TypeOrmModule.forFeature([Image])
],
...
})
...
在上面的代码片断中,我们从之前安装的typeorm模块中导入了TypeOrmModule 。我们使用forRoot 方法将应用程序连接到MySQL数据库并传入数据库凭证。这里需要指出的另一件事是entities 属性,它允许我们在我们的模块中指定实体,它将使我们能够访问你即将创建的Image 实体:我们还将synchronize 属性设置为true ,以自动迁移数据库。
创建图像实体
接下来,让我们来创建我们前面提到的Image实体。为了开始,在src目录下创建一个image.entity.ts文件,并添加下面的代码片段。
TypeScript
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity()
export class Image {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@CreateDateColumn()
dateCreated: Date;
@UpdateDateColumn()
dateUpdated: Date;
}
在上面的代码片段中,我们导入了创建实体所需的装饰器。使用这些装饰器,我们定义了实体的属性。我们有id 字段,使用@PrimaryGeneratedColumn() 装饰器为数据库中的每条记录生成随机ID;name 字段,使用@Column 装饰器存储将被上传的图片名称;dateCreated 和 dateUpdate 字段,使用@CreateDateColumn() 和@UpdateDateColumn() 保存记录的创建和更新日期。
创建上传服务
随着Image实体的创建,让我们创建一个服务来执行CRUD操作以处理文件上传。在app.service.ts 文件中,添加下面的代码片段。
TypeScript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Image } from './image.entity';
@Injectable()
export class AppService {
constructor(
@InjectRepository(Image)
private readonly imageRepository: Repository<Image>,
) {}
async getImages(): Promise<Image[]> {
return this.imageRepository.find();
}
async createImage(image: Image): Promise<Image> {
return this.imageRepository.save(image);
}
async getImage(id: number): Promise<Image> {
return this.imageRepository.findOneBy({ id });
}
async deleteImage(id: number): Promise<void> {
await this.imageRepository.delete(id);
}
}
在上面的代码片段中,我们已经导入了injectRepository 装饰器,将imageRepository 注入到AppService 和Repository ,这为你提供了在数据库中执行一些操作所需的方法。因此,对于createImage 图像服务,我们正在保存被上传的图像的名称,这将通过控制器传递。
创建上传控制器
现在让我们创建控制器来使用这些服务。在app.controller.ts 文件中,添加下面的代码片段。
TypeScript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Image } from './image.entity';
@Injectable()
export class AppService {
constructor(
@InjectRepository(Image)
private readonly imageRepository: Repository<Image>,
) {}
async getImages(): Promise<Image[]> {
return this.imageRepository.find();
}
async createImage(image: Image): Promise<Image> {
return this.imageRepository.save(image);
}
async getImage(id: number): Promise<Image> {
return this.imageRepository.findOneBy({ id });
}
async deleteImage(id: number): Promise<void> {
await this.imageRepository.delete(id);
}
}
在上面的代码片段中,我们导入了几个装饰器,如FileInterceptor 、UploadedFile 、和UseInterceptors 。FileInterceptor() 拦截器到路由处理程序,使用@UploadedFile() 装饰器从请求中提取文件。FileInterceptor() 装饰器是从@nestjs/platform-express 包中导出的。@UploadedFile() 装饰器是从@nestjs/common 输出的。FileInterceptor() 装饰器需要两个参数,fieldName ,它是提供HTML表单中存放文件的字段名称的字符串,以及options ,它是一个MulterOptions类型的可选对象。这是multer构造函数所使用的同一个对象。
multer关于createImage 函数,我们使用上述装饰器来处理文件上传,使用FileInterceptor() 传递图像的字段名,我们修改了FileInterceptor() 函数,通过使用diskStorage 函数指定storage 属性将图像上传到磁盘。然后我们指定了图像的位置,并为图像生成了随机名称。此外,我们还添加了一个filter 属性来限制某些图像格式的上传。现在,我们使用@UploadedFile() 装饰器得到提取的文件,并得到名称,然后将其保存到数据库中。这样,我们就可以使用每张图片的名称从存储位置获取图片。
为了使上述代码工作,你需要在终端运行以下命令来安装multer。
Shell
npm i -D @types/multer
然后,你需要在app.module.ts 文件的导入阵列中注册multer模块。
TypeScript
...
import { MulterModule } from '@nestjs/platform-express';
@Module({
...
MulterModule.register({
dest: './files',
}),],
...
上述配置告诉multer处理文件的上传,以及上传文件的位置。最后但并非最不重要的是,我们应该在src 目录中创建一个files 文件夹来实际存储文件。
服务文件
为了真正地将上传的图片提供给用户,你需要通过运行下面的命令安装serve-static 模块。
外壳
npm install --save @nestjs/serve-static
然后,用下面的代码片断在app.module.ts 文件的导入数组中注册ServeStaticModule 。
TypeScript
...
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
@Module({
...
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'files')
}),],
...
在上面的代码片段中,你已经指定了文件所在的位置,并且可以从那里获得服务。
测试API
现在打开Postman,通过向端点localhost:4000/images 发送POST请求来测试该应用程序,并在请求体中以form-data的形式传递有效载荷。
如果你现在看一下文件文件夹,你应该看到你上传的文件。请随意:也可以测试和玩弄其他的路由。
总结
通过本教程,你已经学会了如何用NestJS和MySQL处理文件上传。你已经学会了如何使用TypeORM连接到MySQL数据库,你还创建了一个实体并将图片上传到NestJS应用程序中。