首页 > 解决方案 > 使用 NestJS 和 GraphQL 访问 MongoDB GridFS 中的文件

问题描述

我正在使用带有 GraphQL 和 MongoDB 的 NestJS。我正在尝试使用 GridFS 使用mongo-gridfs包存储图像文件。

将图像上传到数据库可以正常工作,但是如何访问这些文件?我的意思是,例如我想获取这些文件的源路径并在我的前端使用它

这是我的解析器和服务:

// photo.resolver.ts

import { Resolver, Mutation, Query, Args } from '@nestjs/graphql';
import { GraphQLUpload, FileUpload } from 'graphql-upload';
import { Photo } from './dto/photo.dto';
import { PhotoService } from './services/photo.service';

@Resolver()
export class PhotoResolver {
  constructor(
    private readonly photoService: PhotoService
  ) {}

  @Query(() => ???, { nullable: true })
  async photo(@Args('id', { nullable: true }) id: string) {
    const photo = await this.photoService.findOne(id);
    return ???;
  }

  @Mutation(() => Photo)
  async uploadPhoto(@Args({name: 'file', type: () => GraphQLUpload}) file: FileUpload) {
    return await this.photoService.save(file);
  }
}
// photo.service.ts

import { Connection } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectConnection } from '@nestjs/mongoose';
import { FileUpload } from 'graphql-upload';
import { MongoGridFS } from 'mongo-gridfs';
import { Photo } from '../photo.interface';

@Injectable()
export class PhotoService {
  private fileModel: MongoGridFS;
  
  constructor(
    @InjectConnection() private readonly connection: Connection
  ) {
    this.fileModel = new MongoGridFS(this.connection.db as any, 'photo');
  }  

  async findOne(id: string) {
    return await this.fileModel.findById(id);
  }
  
  async save(file: FileUpload): Promise<Photo> {
    return await this.fileModel.writeFileStream(file.createReadStream(), {
      filename: file.filename,
      contentType: file.mimetype
    });
  }
}

我试过两种方法:

  1. 我使用downloadFile了 my 中的方法photoModel,但它返回Temp本地磁盘目录中此文件的路径。
// photo.service.ts
async findOne(id: string): Promise<string> {
  return await this.fileModel.downloadFile(id); // C:\...\AppData\Local\Temp\189450ef
}

// photo.resolver.ts
@Query(() => String, { nullable: true })
async photo(@Args('id', { nullable: true }) id: string) {
  return id && await this.photoService.findOne(id);
}

它本身可以工作,但在我看来它不是一个合适的解决方案。我希望源路径应该“引导”到我的服务器。

  1. 我使用readFileStream了我的方法photoModel,它返回文件流并添加@Res() res到解析器中的参数。
// photo.service.ts
async findOne(id: string): Promise<GridFSBucketReadStream> {
  return await this.fileModel.readFileStream(id);
}

// photo.resolver.ts
@Query(() => Boolean)
async photo(@Args('id', { nullable: true }) id: string, @Res() res) {
  const photoStream = await this.photoService.findOne(id);
  photoStream.pipe(res);
  return true;
}

现在我在终端中遇到了这样的错误:

[Nest] 12408   - 10.07.2021, 13:02:25   [ExceptionsHandler] dest.on is not a function +27555ms
TypeError: dest.on is not a function

标签: mongodbmongoosegraphqlnestjsgridfs

解决方案


推荐阅读