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

React前端基于graphql-request发送FormData(图片)的实现咨询

当然可以!不过有个小细节需要注意:graphql-request默认是用JSON格式发送请求的,而上传文件(比如图片)需要采用multipart/form-data格式,所以得调整请求的发送方式来适配。我给你整理了前端的实现示例,再补充一点后端的关键配置建议,帮你打通整个流程。

前端实现示例

下面是React组件中使用graphql-request上传图片的完整代码,核心是手动构造FormData并调整请求配置:

import { request } from 'graphql-request';

const ImageUploadForm = () => {
  const handleFileUpload = async (e) => {
    e.preventDefault();
    const selectedFile = e.target.fileInput.files[0];
    if (!selectedFile) return;

    // 1. 定义接收文件的GraphQL mutation
    const uploadMutation = `
      mutation UploadImage($file: Upload!) {
        uploadImage(file: $file) {
          id
          url
          filename
        }
      }
    `;

    // 2. 构造符合GraphQL multipart规范的FormData
    const formData = new FormData();
    // 添加GraphQL查询语句
    formData.append('query', uploadMutation);
    // 添加变量(这里的file值设为null,对应FormData中的文件项)
    formData.append('variables', JSON.stringify({ file: null }));
    // 添加实际的图片文件,键名"0"对应变量中file的索引(多文件时递增)
    formData.append('0', selectedFile);

    try {
      // 3. 发送请求,无需手动设置Content-Type(浏览器会自动添加带boundary的正确头)
      const uploadResult = await request('/graphql', formData);
      console.log('图片上传成功:', uploadResult);
      // 这里可以做后续的UI更新,比如显示上传后的图片
    } catch (error) {
      console.error('图片上传失败:', error.message);
    }
  };

  return (
    <form onSubmit={handleFileUpload}>
      <input type="file" name="fileInput" accept="image/*" />
      <button type="submit" disabled={!e?.target.fileInput?.files?.length}>
        上传图片
      </button>
    </form>
  );
};

export default ImageUploadForm;
后端补充配置建议

因为你用的是express-graphql,它本身不支持文件上传解析,需要搭配graphql-upload中间件来处理multipart/form-data请求,这里给你关键的后端配置代码片段:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { GraphQLUpload, graphqlUploadExpress } = require('graphql-upload');
const { buildSchema } = require('graphql');
const fs = require('fs');
const path = require('path');

const app = express();

// 先添加文件上传解析中间件,限制文件大小和数量
app.use(graphqlUploadExpress({ maxFileSize: 10 * 1024 * 1024, maxFiles: 1 }));

// 定义包含Upload标量的Schema
const schema = buildSchema(`
  scalar Upload

  type Image {
    id: ID!
    url: String!
    filename: String!
  }

  type Mutation {
    uploadImage(file: Upload!): Image!
  }
`);

// 根解析器处理文件上传逻辑
const rootResolver = {
  uploadImage: async ({ file }) => {
    const { createReadStream, filename } = await file;
    const uploadDir = path.join(__dirname, 'uploads');
    // 确保uploads目录存在
    if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir);
    
    const filePath = path.join(uploadDir, filename);
    // 流式写入文件到本地
    await new Promise((resolve, reject) => {
      createReadStream()
        .pipe(fs.createWriteStream(filePath))
        .on('finish', resolve)
        .on('error', reject);
    });

    // 返回图片的访问信息
    return {
      id: Date.now().toString(),
      url: `/uploads/${filename}`,
      filename
    };
  }
};

// 配置GraphQL端点
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootResolver,
  graphiql: true,
}));

// 静态文件服务,让前端可以访问上传的图片
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));

app.listen(4000, () => {
  console.log('服务器运行在 http://localhost:4000/graphql');
});
关键注意事项
  • 前端不要手动设置Content-Type: multipart/form-data,浏览器会自动添加包含boundary的正确请求头,手动设置会导致请求解析失败。
  • 后端必须安装graphql-upload依赖(npm install graphql-upload),否则无法解析文件上传请求。
  • 如果存在跨域问题,记得在express中添加cors中间件来允许前端域名的请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:40:13