如何在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
相关产品推荐
相关产品推荐

