NestJS中如何上传图书时关联封面图并将路径存入MongoDB
实现图书信息与封面图同步上传并绑定MongoDB字段方案
现有代码回顾
1. BookSchema.ts 图书模型定义
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Document } from 'mongoose'; @Schema() export class Book { @Prop() bid: number; @Prop() name: string; @Prop() author: string; @Prop() price: number; @Prop() genres_name: string; @Prop() coverimage: string; } export const bookschema = SchemaFactory.createForClass(Book); export type bookdocument = Book & Document;
2. 现有图片上传控制器(images.controller.ts)
import { Controller, Post, UploadedFile, UseInterceptors, Request, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { ApiTags } from '@nestjs/swagger'; import { diskStorage } from 'multer'; import { extname } from 'path'; import { of } from 'rxjs'; import { BooksService } from 'src/genres/books/books.service'; @ApiTags('Book Cover Images') @Controller('images') export class ImagesController { static a = './uploads/images'; constructor(private readonly bookservice: BooksService) {} @Post('upload') @UseInterceptors( FileInterceptor('file', { storage: diskStorage({ destination: ImagesController.a, filename: (req, file, cb) => { const filename: string = Array(10) .fill(null) .map(() => Math.round(Math.random() * 16).toString(16)) .join(''); return cb(null, `${filename}${extname(file.originalname)}`); }, }), }), ) uploadFile(@UploadedFile() file: Express.Multer.File) { console.log(file); return of({ imageid: file.filename, imagepath: file.destination, originalname: file.originalname, }); } }
具体实现方案
推荐用单接口同步接收图书参数和封面图的方式,符合同步上传的需求:
- 首先在Book模块新增创建图书的接口,同时配置文件拦截器处理封面图上传
// src/genres/books/books.controller.ts import { Controller, Post, UseInterceptors, UploadedFile, Body } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { diskStorage } from 'multer'; import { extname } from 'path'; import { BooksService } from './books.service'; // 自行补充CreateBookDto,定义bid、name、author、price、genres_name字段即可 import { CreateBookDto } from './dto/create-book.dto'; @Controller('books') export class BooksController { constructor(private readonly booksService: BooksService) {} @Post('create') @UseInterceptors( FileInterceptor('cover', { storage: diskStorage({ destination: './uploads/images', filename: (req, file, cb) => { const filename: string = Array(10) .fill(null) .map(() => Math.round(Math.random() * 16).toString(16)) .join(''); cb(null, `${filename}${extname(file.originalname)}`); }, }), }), ) async create( @Body() createBookDto: CreateBookDto, @UploadedFile() file: Express.Multer.File, ) { // 拼接可直接访问的封面路径,和静态资源托管配置对应 const coverPath = `/uploads/images/${file.filename}`; return this.booksService.create({ ...createBookDto, coverimage: coverPath, }); } }
- 配置静态资源托管,保证上传的封面图可以正常访问,修改main.ts:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; async function bootstrap() { const app = await NestFactory.create<NestExpressApplication>(AppModule); // 托管上传目录的静态资源 app.useStaticAssets(join(__dirname, '..', 'uploads'), { prefix: '/uploads/' }); await app.listen(3000); } bootstrap();
- 前端调用规则:
- 请求方式POST,地址
/books/create - 数据格式用form-data,包含图书相关字段,以及
cover字段传选中的封面图文件即可
如果要复用现有图片上传接口,也可以用分两次请求的方案:
- 前端先调用
/images/upload上传封面图,拿到返回的文件名拼接成/uploads/images/${imageid}路径 - 再调用图书创建接口,把拼接好的路径作为
coverimage字段和其他图书参数一起传给后端,直接存入MongoDB即可
内容的提问来源于stack exchange,提问作者M Nouman
相关产品推荐
相关产品推荐

