【问题标题】:Nestjs Apollo graphql upload scalarNestjs Apollo graphql 上传标量
【发布时间】:2019-09-29 12:27:42
【问题描述】:

我正在使用nestjs graphql框架,我想使用apollo标量上传

我已经能够在另一个不包含nestjs的项目中使用标量。

schema.graphql App.module.ts 注册graphql

    GraphQLModule.forRoot({
      typePaths: ['./**/*.graphql'],
      resolvers: { Upload: GraphQLUpload },
      installSubscriptionHandlers: true,
      context: ({ req }) => ({ req }),
      playground: true,
      definitions: {
        path: join(process.cwd(), './src/graphql.classes.ts'),
        outputAs: 'class',
      },
      uploads: {
        maxFileSize: 10000000, // 10 MB
        maxFiles: 5
      }
    }),

pets.resolver.ts 变异创建宠物

@Mutation('uploadFile')
    async uploadFile(@Args('fileUploadInput') fileUploadInput: FileUploadInput) {
        console.log("TCL: PetsResolver -> uploadFile -> file", fileUploadInput);
        return {
            id: '123454',
            path: 'www.wtf.com',
            filename: fileUploadInput.file.filename,
            mimetype: fileUploadInput.file.mimetype
        }
    }

pets.type.graphql

type Mutation {
        uploadFile(fileUploadInput: FileUploadInput!): File!
}
input FileUploadInput{
    file: Upload!
}

type File {
        id: String!
        path: String!
        filename: String!
        mimetype: String!
}

我希望标量可以与 nestjs 一起使用,但我的实际结果是

{"errors":[{"message":"Promise resolver undefined is not a function","locations":[{"line":2,"column":3}],"path":["createPet"],"extensions":{"code":"INTERNAL_SERVER_ERROR","exception":{"stacktrace":["TypeError: Promise resolver undefined is not a function","    at new Promise (<anonymous>)","    at TransformOperationExecutor.transform (E:\\projectos\\Gitlab\\latineo\\latineo-api\\src\\TransformOperationExecutor.ts:119:32)","    at E:\\projectos\\Gitlab\\latineo\\latineo-api\\src\\TransformOperationExecutor.ts:62:40","    at Array.forEach (<anonymous>)","    at TransformOperationExecutor.transform (E:\\projectos\\Gitlab\\latineo\\latineo-api\\src\\TransformOperationExecutor.ts:41:30)","    at _loop_1 (E:\\projectos\\Gitlab\\latineo\\latineo-api\\src\\TransformOperationExecutor.ts:226:43)","    at TransformOperationExecutor.transform (E:\\projectos\\Gitlab\\latineo\\latineo-api\\node_modules\\class-transformer\\TransformOperationExecutor.js:240:17)","    at ClassTransformer.plainToClass (E:\\projectos\\Gitlab\\latineo\\latineo-api\\src\\ClassTransformer.ts:43:25)","    at Object.plainToClass (E:\\projectos\\Gitlab\\latineo\\latineo-api\\src\\index.ts:37:29)","    at ValidationPipe.transform (E:\\projectos\\Gitlab\\latineo\\latineo-api\\node_modules\\@nestjs\\common\\pipes\\validation.pipe.js:50:41)","    at transforms.reduce (E:\\projectos\\Gitlab\\latineo\\latineo-api\\node_modules\\@nestjs\\core\\pipes\\pipes-consumer.js:15:28)","    at process._tickCallback (internal/process/next_tick.js:68:7)"]}}}],"data":null}

【问题讨论】:

标签: javascript node.js graphql apollo nestjs


【解决方案1】:

我通过使用graphql-upload 库解决了这个问题。 首先,我使用来自graphql-uploadGraphQLUpload 为我的标量创建了一个类

import { Scalar } from '@nestjs/graphql';

import { GraphQLUpload } from 'graphql-upload';

@Scalar('Upload')
export class Upload {
  description = 'Upload custom scalar type';

  parseValue(value) {
    return GraphQLUpload.parseValue(value);
  }

  serialize(value: any) {
    return GraphQLUpload.serialize(value);
  }

  parseLiteral(ast) {
    return GraphQLUpload.parseLiteral(ast);
  }
}

我在我的应用程序模块中添加的

@Module({
  imports: [
  ...
    DateScalar,
    Upload,
    GraphQLModule.forRoot({
      typePaths: ['./**/*.graphql'],
     ...
      uploads: {
        maxFileSize: 10000000, // 10 MB
        maxFiles: 5,
      },
    }),
  ...
  ],
...
})
export class ApplicationModule {}

我还在我的 graphql 中添加了上传标量

scalar Upload
...
type Mutation {
  uploadFile(file: Upload!): String
}

并且在我的解析器中工作,我可以访问上传的文件。

  @Mutation()
  async uploadFile(@Args('file') file,) {
    console.log('Hello file',file)
    return "Nice !";
  }

(旁注:我使用https://github.com/jaydenseric/apollo-upload-client#function-createuploadlink 上传文件,在解析器中它是一个节点流)

【讨论】:

  • Lary 你在使用 parseLiteral 时遇到问题,期望 2 个参数 ?parseLiteral(valueNode: ValueNode, variables: Maybe) { return GraphQLUpload.parseLiteral(valueNode, variables) ; }
  • 也许你可以在这个不和谐的频道中提供帮助discordapp.com/channels/520622812742811698/520649487924985885
  • 不,我用过:“apollo-server-express”:“2.8.0”,“graphql-upload”:“^8.0.7”“@types/graphql-upload”:“^ 8.0.0”,你呢? (如果你想要@Lard-man,我已经在这个不和谐中PM我)
  • 对于那些现在尝试这个的人,graphql-upload 包含在apollo-server-express 中。
【解决方案2】:

使用 import {GraphQLUpload} from "apollo-server-express"
Not from 'graphql-upload'

import { Resolver, Mutation, Args } from '@nestjs/graphql';
import { createWriteStream } from 'fs';

import {GraphQLUpload} from "apollo-server-express"

@Resolver('Download')
export class DownloadResolver {
    @Mutation(() => Boolean)
    async uploadFile(@Args({name: 'file', type: () => GraphQLUpload})
    {
        createReadStream,
        filename
    }): Promise<boolean> {
        return new Promise(async (resolve, reject) => 
            createReadStream()
                .pipe(createWriteStream(`./uploads/${filename}`))
                .on('finish', () => resolve(true))
                .on('error', () => reject(false))
        );
    }
    
}

【讨论】:

  • Can't find GraphQLUpload with apollo-server-fastify,你知道这是否适用于 Fastify 吗?提前致谢
  • Apollo Server 3 已移除“GraphQLUpload”,以支持用户为这些功能提供自己的机制。
【解决方案3】:

请注意,此旧版本与 Node 14 不完全兼容。

注意:Apollo Server 内置的文件上传机制在 Node 14 及更高版本中不完全支持,将在 Apollo Server 3 中移除。详情see below

【讨论】:

    【解决方案4】:

    Apollo Server所有版本的正确答案(完全兼容Node 14)

    1. 禁用 Apollo Server 的内置上传处理(对于 apollo 3+ 不需要)并将 graphqlUploadExpress 中间件添加到您的应用程序中。
    import { graphqlUploadExpress } from "graphql-upload"
    import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common"
    
    @Module({
      imports: [
        GraphQLModule.forRoot({
          uploads: false, // disable built-in upload handling (for apollo 3+ not needed)
        }),
      ],
    })
    export class AppModule implements NestModule {
      configure(consumer: MiddlewareConsumer) {
        consumer.apply(graphqlUploadExpress()).forRoutes("graphql")
      }
    }
    
    1. 删除从apollo-server-core 导入的GraphQLUpload 并改为从graphql-upload 导入
    // import { GraphQLUpload } from "apollo-server-core" <-- remove this
    import { FileUpload, GraphQLUpload } from "graphql-upload"
    

    【讨论】:

      猜你喜欢
      • 2020-05-20
      • 2022-08-05
      • 2021-12-10
      • 2021-05-14
      • 2018-08-08
      • 2020-03-21
      • 2019-04-30
      • 2021-01-10
      • 2019-12-30
      相关资源
      最近更新 更多