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

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

在GraphQL Mutation上传图片时获取上传进度

GraphQL本身没有原生提供上传进度追踪能力,但可以通过前端自定义逻辑、客户端扩展或后端配合的方式实现,以下是几种可行方案:

方案1:基于Fetch API的流监听(通用方案)

如果你的GraphQL客户端底层基于Fetch API,可以通过包装文件流来追踪上传进度:

  1. 编写进度追踪的文件包装函数:
function createProgressTrackingFile(file, onProgress) {
  const fileStream = file.stream();
  const totalBytes = file.size;
  let uploadedBytes = 0;

  const trackedStream = new ReadableStream({
    async start(controller) {
      const reader = fileStream.getReader();
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        uploadedBytes += value.length;
        const progress = (uploadedBytes / totalBytes) * 100;
        onProgress(progress, uploadedBytes, totalBytes);
        controller.enqueue(value);
      }
      controller.close();
    }
  });

  return new File([trackedStream], file.name, { type: file.type });
}
  1. 调用Mutation时使用包装后的文件:
const handleUpload = (file) => {
  const trackedFile = createProgressTrackingFile(file, (progress, uploaded, total) => {
    // 这里可以更新UI显示进度
    console.log(`上传进度:${progress.toFixed(2)}%,已上传${uploaded}字节/共${total}字节`);
  });

  AddCaptainScanLicense({
    // 替换原变量中的file为trackedFile
    file: trackedFile,
    // 其他Mutation变量...
  });
};

方案2:Apollo Client扩展(若使用Apollo)

如果你的useAddCaptainLicenseScanMutation基于Apollo Client,可通过apollo-upload-client自定义上传链接来监听进度:

  1. 自定义带进度追踪的上传链接:
import { createUploadLink } from 'apollo-upload-client';

const uploadLink = createUploadLink({
  uri: graphqlEndpoint,
  fetch: async (uri, options) => {
    if (options?.body instanceof FormData) {
      const formData = options.body;
      const fileEntries = Array.from(formData.entries()).filter(([_, val]) => val instanceof File);
      if (fileEntries.length === 0) return fetch(uri, options);

      const totalSize = fileEntries.reduce((sum, [_, file]) => sum + file.size, 0);
      let uploadedSize = 0;

      // 替换FormData中的文件为带进度监听的流
      fileEntries.forEach(([key, file]) => {
        const trackedStream = file.stream().pipeThrough(new TransformStream({
          transform(chunk, controller) {
            uploadedSize += chunk.length;
            const progress = (uploadedSize / totalSize) * 100;
            console.log(`上传进度:${progress.toFixed(2)}%`);
            controller.enqueue(chunk);
          }
        }));
        formData.set(key, new File([trackedStream], file.name, { type: file.type }));
      });
    }
    return fetch(uri, options);
  }
});
  1. 将该链接配置到Apollo Client实例中,后续所有文件上传都会触发进度监听。

方案3:后端配合的Subscription实时进度(适合大文件)

如果后端支持分块接收文件,可以通过GraphQL Subscription实时获取上传进度:

  1. 前端同时发起Mutation和Subscription:
// 生成唯一上传ID
const uploadId = crypto.randomUUID();

// 发起上传Mutation
AddCaptainScanLicense({
  file: yourFile,
  uploadId: uploadId,
  // 其他变量...
});

// 订阅进度更新
const { data: progressData } = useSubscription(
  gql`
    subscription UploadProgress($uploadId: ID!) {
      uploadProgress(uploadId: $uploadId) {
        uploadedBytes
        totalBytes
        progress
      }
    }
  `,
  { variables: { uploadId } }
);

// 处理进度数据
if (progressData) {
  const { uploadedBytes, totalBytes, progress } = progressData.uploadProgress;
  console.log(`已上传${uploadedBytes}字节,总大小${totalBytes}字节,进度${progress}%`);
}
  1. 后端需要在接收文件的过程中,定期向Subscription推送进度数据,具体实现取决于后端技术栈。

内容的提问来源于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 00:12:40