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

如何将文件作为GraphQL mutation变量传递?graphql-upload报Upload值无效错误

问题原因&解决方案

你碰到的错误核心有三个问题:

  1. 前端发送请求时用了application/json格式序列化body,File对象无法被JSON序列化,所以传到服务端变成了空对象{}
  2. 服务端resolver里的mutation名和Schema定义不匹配
  3. ApolloServer默认会自带上传处理逻辑,和你引入的graphql-upload冲突,需要手动关闭

第一步:修改前端graphQLFetch函数,适配文件上传

你需要判断请求里有没有File类型的变量,如果有就用FormData格式提交,不要用JSON:

async function graphQLFetch(query, variables = {}) {
  // 检查变量里是否有File对象
  const hasFile = Object.values(variables).some(val => val instanceof File)
  
  if (hasFile) {
    const formData = new FormData()
    formData.append('query', query)
    formData.append('variables', JSON.stringify(variables, (key, value) => {
      // 把File对象单独提出来,JSON序列化时留占位符
      if (value instanceof File) {
        return null
      }
      return value
    }))
    // 把File对象追加到formData里
    Object.entries(variables).forEach(([key, value]) => {
      if (value instanceof File) {
        formData.append(key, value)
      }
    })
    
    const response = await fetch('/graphql', {
      method: 'POST',
      // 不要手动设置Content-Type,浏览器会自动带上multipart/form-data和边界值
      body: formData
    })
    const result = await response.json()
    return result.data
  } else {
    // 普通请求走原来的逻辑
    const response = await fetch('/graphql', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query, variables })
    })
    const result = await response.json()
    return result.data
  }
}

第二步:修正服务端配置

1. 修正resolver里的mutation名

你Schema里定义的mutation是addThumbnailTest,但resolver里写的是handleThumbnailChange,要对应上:

const resolvers = {
  Upload: GraphQLUpload,
  Mutation: {
    // 这里改名和Schema一致
    addThumbnailTest: async (_, { thumbnailFile }) => {
      // 处理上传的文件,比如读取、存到服务器/云存储
      const { createReadStream, filename, mimetype } = await thumbnailFile
      // 你自己的业务逻辑,返回对应的thumbnailSrc即可
      return `/uploads/${filename}`
    }
  }
}

2. 关闭ApolloServer默认的上传处理,避免和graphql-upload冲突

初始化ApolloServer时加上uploads: false配置:

const server = new ApolloServer({
  typeDefs: fs.readFileSync(path.join(__dirname, 'schema.graphql'), 'utf-8'),
  resolvers,
  // 关闭默认上传逻辑,用你引入的graphql-upload处理
  uploads: false
});

第三步:检查中间件加载顺序

确保graphqlUploadExpress()中间件加载在Apollo中间件之前,你现在的写法是对的,不用改。

修改完之后重新启动服务端测试,就能正常拿到上传的文件了。

内容的提问来源于stack exchange,提问作者tiller1010

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:45:06