ApolloServer+buildSchema实现GraphQL文件上传多阶段报错求助
解决GraphQL文件上传的系列报错问题
问题1:Unknown type "Upload". Did you mean "Float"?
你使用TypeGraphQL的buildSchema生成schema时,同时在ApolloServer配置中传入了手写typeDefs,导致标量Upload未被正确注册;且BuildSchemaOptions不存在Upload字段,直接添加会触发类型不兼容错误。
解决方法:
- 移除ApolloServer配置中的
typeDefs字段——buildSchema会通过Resolver装饰器自动生成完整schema,无需重复定义。 - 在
buildSchema中通过scalarsMap注册GraphQLUpload标量:
import { buildSchema } from 'type-graphql'; import { GraphQLUpload } from 'graphql-upload'; const schema = await buildSchema({ resolvers: [PostResolver, UserResolver, LikeResolver, UploadResolver], validate: false, scalarsMap: [{ type: GraphQLUpload, scalar: GraphQLUpload }], }); const server = new ApolloServer({ schema, cache: 'bounded', context: ({ req, res }): MyContext => ({ req, res }), });
问题2:Variable "$file" got invalid value {}; Upload value invalid
该错误源于Resolver参数定义冗余,将Upload包装成FileInput InputType后,客户端上传的文件无法被正确解析;同时需确保服务器端正确处理multipart请求。
解决方法:
- 简化UploadResolver,直接使用
GraphQLUpload作为参数类型,移除多余的FileInput:
import { Resolver, Mutation, Arg, ObjectType, Field } from 'type-graphql'; import { GraphQLUpload, FileUpload } from 'graphql-upload'; import { finished } from 'stream/promises'; import * as path from 'path'; import * as fs from 'fs'; @ObjectType() class FileResponse { @Field() filename!: string; @Field() mimetype!: string; @Field() encoding!: string; } @Resolver() export class UploadResolver { @Mutation(() => FileResponse) async uploadFile( @Arg('file', () => GraphQLUpload) file: FileUpload, ): Promise<FileResponse> { const { createReadStream, filename, mimetype, encoding } = await file; const stream = createReadStream(); const pathName = path.join(__dirname, `./public/img/post/${filename}`); // 确保目标目录存在,避免写入报错 fs.mkdirSync(path.dirname(pathName), { recursive: true }); const out = fs.createWriteStream(pathName); stream.pipe(out); await finished(out); return { filename, mimetype, encoding }; } }
- 服务器端添加
graphql-upload中间件(Apollo Server v4+需手动配置):
import { graphqlUploadExpress } from 'graphql-upload'; import express from 'express'; const app = express(); // 配置文件大小限制,按需调整 app.use(graphqlUploadExpress({ maxFileSize: 10 * 1024 * 1024, maxFiles: 1 })); await server.start(); server.applyMiddleware({ app });
客户端检查点
- 确保
useUploadFileMutation对应的GraphQL mutation定义正确:
mutation UploadFile($file: Upload!) { uploadFile(file: $file) { filename mimetype encoding } }
- 修正上传函数的参数传递方式,文件需放在
variables字段中:
const [uploadFile] = useUploadFileMutation(); const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { const file = e.target.files?.[0]; if (!file) return; uploadFile({ variables: { file } }); };
内容的提问来源于stack exchange,提问作者poggersbasedcringe
相关产品推荐
相关产品推荐

