tauri项目添加多文件下载功能,并支持下载进度回调显示在前端页面上

支持多文件同时下载,以及选中下载目录,并且支持下载进度回显在界面上,下载是在rust端实现的,通过emit事件来将下载进度发送给前端,前端通过listen监听下载进度的事件,然后通过传递下载进度的消息,区分每一个文件的下载进度,再显示到界面上

rust端多文件下载

通过定义一个download_file下载函数,然后传递进来下载url,保存的路径,以及文件id,保存路径可以为空字符串,这样的话,就会默认保存到电脑的下载文件夹中,file_id是文件标识,可以是id或者文件名等,要保证唯一,因为是通过这个id来回调下载进度事件通知的

rust 复制代码
#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct DownloadProgress {
    file_id: String,
    downloaded: u64,
    total: u64,
}

#[tauri::command]
pub async fn download_file(
    app: AppHandle,
    url: String,
    save_path: String,
    file_id: String,
) -> Result<(), String> {
    let client = Client::new();
    let resp = client.get(&url).send().await.map_err(|e| e.to_string())?;
    // if save path is empty
    let mut save_path = save_path;
    let file_name = url.split('/').last().unwrap();
    if save_path.is_empty() {
        let file_path = app
            .path()
            .resolve(file_name, BaseDirectory::Download)
            .expect("failed to resolve resource");
        save_path = file_path.to_str().unwrap().to_string();
    }
    let total_size = resp.content_length();
    let mut stream = resp.bytes_stream();
    let mut file = File::create(&save_path).map_err(|e| e.to_string())?;
    let mut downloaded: u64 = 0;

    while let Some(chunk) = stream.next().await {
        let chunk = chunk.map_err(|e| e.to_string())?;
        file.write_all(&chunk).map_err(|e| e.to_string())?;
        downloaded += chunk.len() as u64;
        app.emit(
            "download_progress",
            DownloadProgress {
                file_id: file_id.clone(),
                downloaded,
                total: total_size.unwrap_or(0),
            },
        )
        .unwrap();
    }
    Ok(())
}

前端调用下载

通过invoke来触发一个下载事件

rust 复制代码
    await invoke('download_file', {
        url,
        savePath,
        fileId,
    })

然后通过监听download_progress事件,拿到下载进度的消息:

javascript 复制代码
const downloadProgress = ref(0)

listen('download_progress', (event: any) => {
    console.log(`downloading fileId--- ${event.payload.fileId}`)
    console.log(`downloading downloaded--- ${event.payload.downloaded}`)
    console.log(`downloading total--- ${event.payload.total}`)
    downloadProgress.value = Number(
        ((event.payload.downloaded / event.payload.total) * 100).toFixed(2)
    )
})

完整项目代码可以在我的开源项目中查看:

github.com/Sjj1024/Pak...

相关推荐
烬羽1 分钟前
给 Agent 一个检索式记忆:把对话历史存进 Milvus,该记的都记得
javascript·数据库·agent
磐链科技11 分钟前
区块链开发入门实战:用 Hardhat 与 Ethers.js 搭建你的第一个 DApp
开发语言·javascript·区块链
码艺-Alimjan25 分钟前
维吾尔语数字转文本
java·javascript·python·算法·go
可乐鸡翅yeah_25 分钟前
hls.js 多实例并发踩坑,多视频页面播放器内存与冲突问题解决
开发语言·前端·javascript·音视频·hls·m3u8·m3u8在线播放
涛涛ing33 分钟前
你的页面为什么总是卡成PPT?2026年,90%的前端都忽略了主线程
前端
SoaringHeart34 分钟前
Flutter 进阶 | 组件封装:用 CustomPainter 实现光环动画组件AnimatedHalo
前端·flutter
IT_陈寒39 分钟前
JavaScript的隐式转换太坑了,我的==比较怎么就炸了?
前端·人工智能·后端
雪芽蓝域zzs1 小时前
第十四节:后端返回权限动态路由
前端·javascript·vue.js
小磊哥er1 小时前
Wonder Claude Code - 一个可运行的、教学级的 Claude Code 精简复刻
javascript·ai编程
Rain5091 小时前
谁动了我的 URL?——记一次微前端“灵异 Bug“的排查实录
前端·vue.js·人工智能·前端框架·bug·ai编程