使用electron-dl下载多个文件时进度条显示异常如何解决?
问题原因
你当前触发的两个下载任务为完全独立的实例,electron-dl的进度回调、完成回调均为单文件维度统计,没有做全局总进度聚合:小体积的svg文件先下载完成时,它的单文件进度100%会直接覆盖全局进度展示,同时它的完成回调会直接把进度重置为0,导致exe的下载进度无法正常展示。
修改方案
主进程(main.ts)修改
给每个下载任务增加唯一标识,进度和完成回调都携带该标识,方便渲染层区分不同任务的状态:
ipcMain.on('download', (event, info) => { const taskId = info.taskId info.properties.onTotalProgress = (status) => mainWindow.webContents.send('download progress', {taskId, ...status}); download(BrowserWindow.getFocusedWindow(), info.url, info.properties) .then((dl) => mainWindow.webContents.send('download complete', {taskId, savePath: dl.getSavePath()}) ).catch(console.error); });
渲染进程(App.tsx)修改
新增全局任务状态管理,聚合所有下载任务的进度计算总进度,等所有任务全部完成后再重置进度:
import { useState, useEffect } from 'react' // ...其他业务逻辑 /* 新增状态:维护所有下载任务的进度、完成状态 */ const [downloadTasks, setDownloadTasks] = useState<Record<string, { total: number, transferred: number, completed: boolean }>>({ 'exe-task': { total: 0, transferred: 0, completed: false }, 'svg-task': { total: 0, transferred: 0, completed: false } }) const [progressNumber, setProgressNumber] = useState(0) useEffect(() => { const downloadPath = path.resolve('/', './exes'); const downloadPathWindows = `${downloadPath}\\${index}`; // 发起exe下载,携带任务ID ipcRenderer.send('download', { taskId: 'exe-task', url: `https://adv.com${book.SmartBookUrl}`, properties: { directory: downloadPathWindows, }, }); // 发起svg下载,携带任务ID ipcRenderer.send('download', { taskId: 'svg-task', url: `https://adv.com${book.CoverImageUrl}`, properties: { directory: downloadPathWindows, }, }); // 进度事件监听 const handleProgress = (event, {taskId, total, transferred}) => { setDownloadTasks(prev => { const newTasks = { ...prev, [taskId]: { ...prev[taskId], total, transferred } } // 计算全局总进度 const allTotal = Object.values(newTasks).reduce((sum, task) => sum + task.total, 0) const allTransferred = Object.values(newTasks).reduce((sum, task) => sum + task.transferred, 0) const totalPercent = allTotal > 0 ? Math.floor((allTransferred / allTotal) * 100) : 0 setProgressNumber(totalPercent) return newTasks }) } // 完成事件监听 const handleComplete = (event, {taskId}) => { setDownloadTasks(prev => { const newTasks = { ...prev, [taskId]: { ...prev[taskId], completed: true } } // 所有任务完成后再重置进度 const allCompleted = Object.values(newTasks).every(task => task.completed) if (allCompleted) { setProgressNumber(0) // 可在此处添加全部下载完成后的业务逻辑 } return newTasks }) } ipcRenderer.on('download progress', handleProgress) ipcRenderer.on('download complete', handleComplete) // 组件卸载时移除监听,避免内存泄漏 return () => { ipcRenderer.removeListener('download progress', handleProgress) ipcRenderer.removeListener('download complete', handleComplete) } }, [])
补充优化点
如果提前已知两个文件的总大小(如你提到的总大小5MB),可以直接把全局总大小写死为5 * 1024 * 1024,替换进度计算逻辑里的allTotal变量,避免刚下载时仅返回单个文件大小导致的进度跳变问题,展示会更平滑。
内容的提问来源于stack exchange,提问作者Tolga Günaydın
相关产品推荐
相关产品推荐

