You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
    });
}
}

具体实现方案

推荐用单接口同步接收图书参数和封面图的方式,符合同步上传的需求:

  1. 首先在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,
    });
  }
}
  1. 配置静态资源托管,保证上传的封面图可以正常访问,修改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();
  1. 前端调用规则:
  • 请求方式POST,地址/books/create
  • 数据格式用form-data,包含图书相关字段,以及cover字段传选中的封面图文件即可

如果要复用现有图片上传接口,也可以用分两次请求的方案:

  • 前端先调用/images/upload上传封面图,拿到返回的文件名拼接成/uploads/images/${imageid}路径
  • 再调用图书创建接口,把拼接好的路径作为coverimage字段和其他图书参数一起传给后端,直接存入MongoDB即可

内容的提问来源于stack exchange,提问作者M Nouman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:15:06