NestJS build blog system (10) – graph bed module
preface
Here do chart bed module mainly to save resources, at the same time convenient picture reuse. The basic function has the picture list and the picture adds, uploads the picture. In order to reuse resources, the image module needs to save the image path and MD5 value to calculate whether the image MD5 value exists when uploading the image.
Develop the chart bed module
nest g mo modules/picture
nest g co modules/picture
nest g s modules/picture
Entity DTO VO
// src/modules/picture/entity/picture.entity.ts
import { Common } from 'src/common/entity/common.entity';
import { Entity, Column } from 'typeorm';
@Entity(a)export class Picture extends Common{
// Image path
@Column('text')
src: string;
// File signature
@Column('text')
sign: string;
}
Copy the code
// src/modules/picture/dto/picture.dto.ts
import { IsNotEmpty } from "class-validator";
export class PictureDTO {
/** * image path *@example /upload/static/1.png
*/
@IsNotEmpty({ message: 'Please enter picture path' })
readonly src: string;
}
Copy the code
// src/modules/picture/dto/picture-create.dto.ts
import { PictureDTO } from "./picture.dto";
export class PictureCreateDto extends PictureDTO {
/** * md5 *@example asdfghjkl* /
readonlysign? :string;
}
Copy the code
// src/modules/picture/vo/picture-info.dto.ts
import { SuccessVO } from "src/common/dto/success.dto";
import { PictureDTO } from ".. /dto/picture.dto";
export class PictureInfoItem extends PictureDTO{}
export class PictureInfoVO {
info: PictureInfoItem
}
export class PictureInfoSuccessVO extends SuccessVO {
data: {
info: PictureInfoItem
}
}
Copy the code
// src/modules/picture/vo/picture-list.dto.ts
import { PaginationDTO } from "src/common/dto/pagination.dto";
import { SuccessVO } from "src/common/dto/success.dto";
import { PictureDTO } from ".. /dto/picture.dto";
export class PictureListItem extends PictureDTO {}
export class PictureListVO {
list: PictureListItem[]
pagination: PaginationDTO
}
export class PictureListSuccessVO extends SuccessVO {
data: {
list: PictureListItem[]
pagination: PaginationDTO
}
}
Copy the code
Refer to the entity
// src/modules/picture/picture.modules.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Picture } from './entity/picture.entity';
import { PictureController } from './picture.controller';
import { PictureService } from './picture.service';
@Module({
imports: [
TypeOrmModule.forFeature([Picture]),
],
controllers: [PictureController],
providers: [PictureService]
})
export class PictureModule {}
Copy the code
The controller
import { Controller, Get, Post, Query, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { PageDTO } from 'src/common/dto/Page.dto';
import { PictureService } from './picture.service';
import { PictureInfoSuccessVO, PictureInfoVO } from './vo/picture-info.vo';
import { PictureListSuccessVO, PictureListVO } from './vo/picture-list.vo';
@ApiTags('Chart bed Module')
@Controller('picture')
export class PictureController {
constructor(
private pictureService: PictureService
) {}
@ApiOkResponse({ description: 'Picture list'.type: PictureListSuccessVO })
@Get('list')
async getMany(
@Query() pageDto: PageDTO
): Promise<PictureListVO> {
return await this.pictureService.getMany(pageDto)
}
@ApiOkResponse({ description: 'Upload picture'.type: PictureInfoSuccessVO })
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
async upload(
@UploadedFile() file:any) :Promise<PictureInfoVO> {
console.log('controller', {file})
return await this.pictureService.upload(file)
}
}
Copy the code
Service
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { PageDTO } from 'src/common/dto/Page.dto';
import { getPagination } from 'src/utils/index.util';
import { Repository } from 'typeorm';
import { PictureCreateDto } from './dto/picture-create';
import { Picture } from './entity/picture.entity';
import { PictureInfoVO } from './vo/picture-info.vo';
import * as fs from 'fs';
import { encryptFileMD5 } from 'src/utils/cryptogram.util';
import { uploadStaticSrc } from 'src/config/upload/upload.config';
@Injectable(a)export class PictureService {
constructor(
@InjectRepository(Picture)
private readonly pictureRepository: Repository<Picture>,
) {}
async getMany(
pageDto: PageDTO
) {
const { page, pageSize } = pageDto
const getList = this.pictureRepository
.createQueryBuilder('picture')
.select([
'picture.src',
])
.skip((page - 1) * pageSize)
.take(pageSize)
.getManyAndCount()
const [list, total] = await getList
const pagination = getPagination(total, pageSize, page)
return {
list,
pagination,
}
}
async create(
pictureCreateDTO: PictureCreateDto
): Promise<PictureInfoVO> {
const picture = new Picture()
picture.src = pictureCreateDTO.src
picture.sign = pictureCreateDTO.sign
const result = await this.pictureRepository.save(picture)
return {
info: result
}
}
async getOneBySign(sign: string) {
return await this.pictureRepository
.createQueryBuilder('picture')
.where('picture.sign = :sign', { sign })
.getOne()
}
async upload(file: any) {
const { buffer } = file
const currentSign = encryptFileMD5(buffer)
const hasPicture = await this.getOneBySign(currentSign)
if (hasPicture) {
return {
info: {
src: hasPicture.src,
isHas: true,}}}const arr = file.originalname.split('. ')
const fileType = arr[arr.length - 1]
const fileName = currentSign + '. ' + fileType
fs.writeFileSync(`./upload/${fileName}`, buffer)
const src = uploadStaticSrc + fileName
this.create({ src, sign: currentSign })
return {
info: {
src,
isHas: false}}}}Copy the code
The static file path needs to be set
// src/config/upload/upload.config.ts
/ / static file path localhost/static/upload/XXX. JPG
export const uploadStaticSrc = '/static/upload/'
Copy the code
// src/main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './filters/http-exception.filter';
import { TransformInterceptor } from './interceptor/transform.interceptor';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { uploadStaticSrc } from './config/upload/upload.config';
import { join } from 'path';
import { NestExpressApplication } from '@nestjs/platform-express';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useGlobalPipes(new ValidationPipe())
app.useGlobalInterceptors(new TransformInterceptor())
app.useGlobalFilters(new HttpExceptionFilter())
app.useStaticAssets(join(__dirname, '.. '.'upload'), {
prefix: uploadStaticSrc,
});
const options = new DocumentBuilder()
.setTitle('blog-serve')
.setDescription('Interface Document')
.setVersion('1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('swagger-doc', app, document);
await app.listen(3000);
}
bootstrap();
Copy the code
At this point, the chart bed module with duplicate lookup function has been completed, although only the list view function and upload function, but enough to facilitate the reuse of resources
reference
- NestJS
- NestJS Chinese website
- Code for this section
A series of
- NestJS build blog system (a) – build a framework
- NestJS build blog system (2) – write static article CURD
- NestJS build blog system (3) – using TypeORM+Mysql to achieve data persistence
- NestJS build blog system (four) – use interceptor, exception filter to achieve a unified return format
- Use class-validator+ class validator to implement form validation
- NestJS build blog system (6) – Use Swagger to generate documents
- NestJS build blog system (7) – use JWT to register and log in
- NestJS build blog system (eight) – project optimization
- NestJS build blog system (nine) – tag module