如何在Apollo Server v4中通过graphql-upload实现文件上传?
解决Apollo Server v4 + Express + TypeGraphQL 文件上传参数验证错误问题
你遇到的ApolloError: Argument Validation Error核心原因是Apollo Server v4已移除内置的multipart/form-data处理能力,同时TypeGraphQL需要正确配置GraphQLUpload标量才能识别上传参数。以下是完整解决方案:
1. 配置Express的graphql-upload中间件
在Express应用中,必须先添加graphqlUploadExpress中间件处理文件上传请求,且要放在Apollo Server的中间件之前:
import express from "express"; import { ApolloServer } from "@apollo/server"; import { expressMiddleware } from "@apollo/server/express4"; import { graphqlUploadExpress } from "graphql-upload"; const app = express(); // 先添加文件上传中间件,可配置上传大小限制 app.use(graphqlUploadExpress({ maxFileSize: 10 * 1024 * 1024, maxFiles: 1 })); // 初始化Apollo Server const server = new ApolloServer({ schema: yourGeneratedSchema }); await server.start(); // 挂载Apollo中间件 app.use( "/graphql", express.json(), expressMiddleware(server, { context: async ({ req }) => ({ token: req.headers.token }), }) );
2. 注册TypeGraphQL的Upload标量
生成TypeGraphQL Schema时,需将GraphQLUpload标量注册到schema中:
import { buildSchema } from "type-graphql"; import { GraphQLUpload } from "graphql-upload"; import { FileResolver } from "./resolvers/FileResolver"; const schema = await buildSchema({ resolvers: [FileResolver], // 注册Upload标量,让TypeGraphQL识别该类型 scalarsMap: [{ type: GraphQLUpload, scalar: GraphQLUpload }], });
3. 修正Resolver中的类型定义
无需自定义Upload接口,直接使用graphql-upload提供的类型,避免类型不匹配:
import { Mutation, Arg, Resolver } from "type-graphql"; import { GraphQLUpload, Upload } from "graphql-upload"; import { createWriteStream } from "fs"; import { join } from "path"; @Resolver() export class FileResolver { @Mutation(() => Boolean) async uploadFile( @Arg("picture", () => GraphQLUpload) { createReadStream, filename }: Upload ): Promise<boolean> { return new Promise((resolve, reject) => { createReadStream() // 使用join拼接路径更安全,避免__dirname层级错误 .pipe(createWriteStream(join(__dirname, "../../../images", filename))) .on("finish", () => resolve(true)) .on("error", (err) => { console.error(err); reject(false); }); }); } }
4. 前端Apollo Client配置确认
确保前端使用apollo-upload-client的createUploadLink替代默认的createHttpLink:
import { ApolloClient, InMemoryCache } from "@apollo/client"; import { createUploadLink } from "apollo-upload-client"; const client = new ApolloClient({ link: createUploadLink({ uri: "http://localhost:4000/graphql", }), cache: new InMemoryCache(), });
关键注意事项
- 确保
graphql-upload版本为14.x,与graphql@16.x和Apollo Server v4兼容 - 提前创建上传目录(如
images),否则会出现文件写入失败错误 - 移除原代码中
new Promise(async (resolve, reject)的多余async,避免潜在的Promise嵌套问题
内容的提问来源于stack exchange,提问作者mohammad
相关产品推荐
相关产品推荐

