typescript - 如何使用 NestJS graphql 上传多个文件?
问题描述
我想创建一个突变,向服务器发送一个包含字符串字段的对象和一个包含照片和描述数组的字段。这是我的输入类型:
import { InputType, Field } from '@nestjs/graphql';
import {
IsString,
MinLength,
ValidateNested,
IsOptional,
IsBoolean,
IsUUID,
IsNotEmptyObject,
} from 'class-validator';
import { FileUpload } from 'graphql-upload';
import { GraphQLUpload } from 'apollo-server-express';
@InputType()
export class HouseTourInput {
@Field()
@IsString()
@MinLength(2)
title: string;
@Field()
@IsString()
@MinLength(2)
@IsOptional()
summary: string;
@Field()
@IsString()
@MinLength(2)
@IsOptional()
category: string;
@Field()
@IsBoolean()
@IsOptional()
featured: boolean;
@Field()
@IsUUID()
authorId: string;
@Field(type => [SlidesInput])
@ValidateNested({ each: true })
slides: SlidesInput[];
}
@InputType()
class SlidesInput {
@Field(() => GraphQLUpload)
@IsNotEmptyObject()
photo: FileUpload;
@Field()
@IsString()
@MinLength(2)
description: string;
}
这是我的解析器:
@Resolver(of => HouseTour)
export class AdminResolver {
constructor(private adminService: AdminService) {}
@Mutation(returns => HouseTour)
async createHouseTour(
@Context('user') user: IMe,
@Args('input') input: HouseTourInput,
) {
console.log(input);
// More code irrelevant to this question
}
输入永远不会记录在控制台中,因为代码似乎永远不会超出验证点。这是错误日志:
TypeError: Promise resolver undefined is not a function
at new Promise (<anonymous>)
at TransformOperationExecutor.transform (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/TransformOperationExecutor.js:139:32)
at TransformOperationExecutor.transform (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/TransformOperationExecutor.js:273:43)
at /Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/TransformOperationExecutor.js:73:40
at Array.forEach (<anonymous>)
at TransformOperationExecutor.transform (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/TransformOperationExecutor.js:45:19)
at TransformOperationExecutor.transform (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/TransformOperationExecutor.js:273:43)
at ClassTransformer.plainToClass (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/ClassTransformer.js:17:25)
at Object.plainToClass (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/class-transformer/index.js:29:29)
at ValidationPipe.transform (/Users/babatundeadeyemi/workspace/234homesbackend/node_modules/@nestjs/common/pipes/validation.pipe.js:42:39)
我不知道还能做什么。我用谷歌搜索并没有找到答案。
解决方案
我不确定您的错误的根本原因是什么,但我自己偶然发现了 graphql 上传问题,这令人沮丧。
幸运的是,我遇到了以下 github 问题,它为我提供了一个可行的解决方案。需要禁用apollo内部graphql的上传,使用graphql-upload
这是我在 NestJS GraphQL 上上传多张图片的最终解决方案。确保在项目的根目录中有一个上传文件夹。
src/app.module.ts
import { GraphQLUpload, graphqlUploadExpress } from "graphql-upload"
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common"
@Module({
imports: [
GraphQLModule.forRoot({
resolvers: { Upload: GraphQLUpload }, // define the Upload Scalar
typePaths: ['./**/*.graphql'],
uploads: false, // disable built-in upload handling
}),
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(graphqlUploadExpress()).forRoutes("graphql")
}
}
src/app.resolver.ts
import { Args, Mutation, Query, Resolver} from '@nestjs/graphql';
import { UseGuards, Inject, Post } from '@nestjs/common';
import { createWriteStream } from 'fs';
import { FileUpload, GraphQLUpload } from "graphql-upload";
@Resolver()
export class AppResolvers {
@Mutation('uploadImages')
async uploadFile(@Args('images', {type: () => GraphQLUpload}) imgs: Promise<FileUpload>[]): Promise<Promise<string>[]> {
return await Promise.all(
imgs.map(async (img: Promise<FileUpload>) : Promise<Promise<string>>=>{
const { filename, mimetype, encoding, createReadStream } = await img;
console.log("attachment:", filename, mimetype, encoding)
const stream = createReadStream();
return new Promise((resolve,reject) =>{
stream.on('end', () => {console.log("ReadStream Ended")})
.on('close', () => {console.log("ReadStream Closed")})
.on('error', (err) => {console.error("ReadStream Error",err)})
.pipe(createWriteStream(`./upload/${filename}`))
.on('end', () => {
console.log("WriteStream Ended");
resolve("end")
})
.on('close', () => {
console.log("WriteStream Closed");
resolve("close")
})
.on('error',(err) => {
console.log("WriteStream Error",err);
reject("error")
});
});
})
)
}
}
src/app.graphql
scalar Upload
type Mutation {
uploadImages(
images: [Upload]
): [String]
}
推荐阅读
- javascript - p5.js:当我的鼠标悬停在正在处理的草图中的不同元素上时,如何使文本出现?
- javascript - onload 刚刚创建的 4 个 img 元素
- android - 如何调用意图颤动以打开电话信息菜单?
- java - 小米和OPPO等中国ROM的工作管理器,在电池优化时,将预定的工作延迟增加几个小时
- javascript - javascript中的异步编程是什么意思?
- unicode - 这个字符是如何编码的?◡̈
- java - 如何从其他类方法变量中设置全局变量?
- powershell - PowerShell正则表达式删除提取Windows补丁到C盘根目录的文件夹
- javascript - How do you get around NATs using WebRTC without a TURN server?
- python - recursively go through list to calculate the percentage change between two items at every n elements