I'm working with NestJS with GraphQL and MongoDB.
I'm trying store image files using GridFS using mongo-gridfs package.
Uploading images to database works fine, but how can I access to this files? I mean for example I want to get source path of this files and use it in my frontend
Here is my resolver and service:
// 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
});
}
}
I've tried two approached:
- I used
downloadFilemethod from myphotoModel, but it returns path to this file in myTempdirectory in local disk.
// 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);
}
It works per se but it doesn't look to me as a proper solution. I'd prefer that source path should "lead" to my server.
- I used
readFileStreammethod from myphotoModel, which return filestream and added@Res() resto arguments in resolver.
// 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;
}
And now I've got such an error in terminal:
[Nest] 12408 - 10.07.2021, 13:02:25 [ExceptionsHandler] dest.on is not a function +27555ms
TypeError: dest.on is not a function