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

使用graphql-upload实现Node.js客户端向GraphQL接口上传文件问题咨询

Node.js 客户端Apollo GraphQL文件上传解决方案

错误原因排查

你的两个实现方案都存在破坏二进制文件内容的问题,对应错误点如下:

  • 第一个方案错误
    1. 调用fs.createReadStream时指定了encoding: "utf8",会将二进制图片文件按UTF-8规则转成字符串,破坏原始二进制结构,直接导致文件大小翻倍、内容损坏
    2. 普通GraphQL请求客户端默认不支持GraphQLUpload规范的多部分请求格式,直接传递流不会自动完成form-data结构拼接
  • 第二个方案错误
    执行streamToString将文件流转为字符串的操作同样破坏了原始二进制内容,上传的不是完整的图片文件,自然无法正常解析使用

正确实现方案

遵循Apollo GraphQL上传规范,直接传递原始二进制读流到formData即可,无需做任何编码转换:

依赖安装(如未安装)

npm i form-data axios graphql

完整代码实现

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
const { print, gql } = require('graphql');

// 定义上传Mutation
const UPLOAD = gql`
  mutation UploadFile($file: Upload!) {
    uploadFile(file: $file)
  }
`;

async function upload(GRAPHQL_URL, apiKey) {
  const formData = new FormData();

  // 配置GraphQL请求参数
  formData.append(
    "operations",
    JSON.stringify({ 
      query: print(UPLOAD), 
      variables: { file: null } 
    })
  );

  // 配置文件到variables的映射关系
  formData.append(
    "map",
    JSON.stringify({
      "0": ["variables.file"],
    })
  );

  // *注意:创建读流时不要添加encoding配置,默认输出二进制Buffer流*
  const fileStream = fs.createReadStream(path.join(__dirname, "image.png"));

  // 追加文件,手动指定文件名和mimetype,避免服务端识别异常
  formData.append("0", fileStream, {
    filename: "image.png",
    contentType: "image/png"
  });

  // 发送请求
  const { data } = await axios.post(GRAPHQL_URL, formData, {
    headers: {
      "X-API-KEY": apiKey,
      // 必须合并formData自动生成的请求头,包含multipart分隔符配置
      ...formData.getHeaders()
    },
    // 可选:大文件上传时放开大小和超时限制
    maxBodyLength: Infinity,
    timeout: 60000
  });

  return data;
}

核心注意事项

  • 所有操作不要修改原始二进制流,禁止将流转为字符串、指定非默认编码等操作
  • 必须手动指定文件的filename和contentType,避免服务端解析时丢失mimetype
  • 请求头必须包含form-data自动生成的multipart/form-data类型和boundary参数,否则服务端无法正常解析请求体

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 09:00:03