You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ApolloServer+buildSchema实现GraphQL文件上传多阶段报错求助

解决GraphQL文件上传的系列报错问题

问题1:Unknown type "Upload". Did you mean "Float"?

你使用TypeGraphQL的buildSchema生成schema时,同时在ApolloServer配置中传入了手写typeDefs,导致标量Upload未被正确注册;且BuildSchemaOptions不存在Upload字段,直接添加会触发类型不兼容错误。

解决方法:

  1. 移除ApolloServer配置中的typeDefs字段——buildSchema会通过Resolver装饰器自动生成完整schema,无需重复定义。
  2. 在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请求。

解决方法:

  1. 简化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 };
  }
}
  1. 服务器端添加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 });

客户端检查点

  1. 确保useUploadFileMutation对应的GraphQL mutation定义正确:
mutation UploadFile($file: Upload!) {
  uploadFile(file: $file) {
    filename
    mimetype
    encoding
  }
}
  1. 修正上传函数的参数传递方式,文件需放在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 06:54:36