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

如何在GraphQL Mutation中跟踪前端图片上传进度?

如何在GraphQL Mutation上传图片时跟踪上传进度

你已经实现了图片的成功上传,要跟踪上传进度并展示到前端进度条,可通过以下几种方式实现:

方法1:自定义带进度监听的Fetch函数

如果你的GraphQL客户端支持自定义fetch逻辑,可以替换为基于XMLHttpRequest的实现,直接监听上传进度:

// 自定义带进度回调的fetch函数
function fetchWithProgress(url: string, options: RequestInit & { onProgress?: (progress: number) => void }) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', url);

    // 监听上传进度事件
    xhr.upload.addEventListener('progress', (event) => {
      if (event.lengthComputable && options.onProgress) {
        const progressPercent = Math.round((event.loaded / event.total) * 100);
        options.onProgress(progressPercent);
      }
    });

    xhr.addEventListener('load', () => {
      const response = new Response(xhr.responseText, {
        status: xhr.status,
        statusText: xhr.statusText,
      });
      resolve(response);
    });

    xhr.addEventListener('error', () => reject(new Error('上传请求失败')));
    xhr.send(options.body);
  });
}

// 创建客户端时传入自定义fetch
const client = graphqlRequestClient(graphqlEndpoint, {
  fetch: (url, options) => fetchWithProgress(url, {
    ...options,
    onProgress: (progress) => {
      // 这里可以将进度存入状态管理,比如React的useState
      console.log('当前上传进度:', progress);
    },
  }),
});

// 初始化Mutation Hook
const { mutate: addProfilePicture } = useAddProfilePictureMutation<Error>(client, {
  onSuccess: (_data) => console.log('上传成功:', _data),
});

方法2:利用客户端内置的进度回调(如果支持)

部分GraphQL客户端(如urql、Apollo Client)允许在Mutation配置或调用时传入进度回调,直接监听上传状态:

import { useState } from 'react';

// 定义状态存储上传进度
const [uploadProgress, setUploadProgress] = useState(0);

const { mutate: addProfilePicture } = useAddProfilePictureMutation<Error>(
  graphqlRequestClient(graphqlEndpoint),
  {
    onSuccess: (_data) => console.log('上传成功:', _data),
    // 若客户端支持,在fetch选项中传入进度回调
    fetchOptions: {
      onProgress: (progress: number) => setUploadProgress(progress),
    },
  }
);

// 调用上传方法时传入文件
const handleUpload = (file: File) => {
  addProfilePicture({ file }, {
    // 也可在调用时通过context传递进度回调
    context: {
      onProgress: (p) => setUploadProgress(p),
    },
  });
};

方法3:手动构造Multipart请求

如果客户端不支持进度监听,可手动构造GraphQL的Multipart上传请求,直接用XMLHttpRequest控制:

import { useState } from 'react';

const [uploadProgress, setUploadProgress] = useState(0);

const handleUpload = (file: File) => {
  const formData = new FormData();
  // 构造GraphQL Mutation内容
  const mutation = `
    mutation AddProfilePicture($file: Upload!) {
      addProfilePicture(file: $file) {
        id
        url
      }
    }
  `;

  // 按照GraphQL Multipart规范组装FormData
  formData.append('operations', JSON.stringify({
    query: mutation,
    variables: { file: null },
  }));
  formData.append('map', JSON.stringify({ '0': ['variables.file'] }));
  formData.append('0', file);

  const xhr = new XMLHttpRequest();
  xhr.open('POST', graphqlEndpoint);

  // 监听上传进度
  xhr.upload.addEventListener('progress', (event) => {
    if (event.lengthComputable) {
      const progressPercent = Math.round((event.loaded / event.total) * 100);
      setUploadProgress(progressPercent);
    }
  });

  xhr.addEventListener('load', () => {
    const response = JSON.parse(xhr.responseText);
    console.log('上传成功:', response.data);
  });

  xhr.addEventListener('error', () => console.error('上传失败'));
  xhr.send(formData);
};

前端进度条展示

有了uploadProgress状态后,直接在JSX中渲染进度条:

<div style={{ width: '100%', height: '24px', backgroundColor: '#e0e0e0', borderRadius: '4px' }}>
  <div
    style={{
      width: `${uploadProgress}%`,
      height: '100%',
      backgroundColor: '#2196F3',
      borderRadius: '4px',
      transition: 'width 0.2s ease-in-out',
    }}
  />
</div>
<p>当前进度: {uploadProgress}%</p>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:16:17