electron展示下载进度条
我们使用electron下载文件时,会发现不像浏览器一样会有地方展示下载进度,这导致下载一些大文件时不知道下载进度到哪里了
下面我们通过electron提供的will-download监听和element-plus中的ElNotification和ElProgress组件实现这一功能

实现逻辑
- 触发下载文件这一操作
- 监听下载开始、下载进度、下载结束
- 根据监听内容操作vnode展示加载进度
1、触发下载文件这一操作
使用electron中ipcMain模块接受页面中发送来的指令
// main.js 部分代码 通过这个打开****.vue界面
var win = new BrowserWindow();
// download.js 部分代码
const { ipcMain, dialog } = require('electron')
let filePath = '';// 监听渲染进程发出的download事件
const webContents = win.webContents;ipcMain.on('download', (evt, args) => {const fileArr = args.split("/");let ext = path.extname(args)let filters = [{ name: '全部文件', extensions: ['*'] }]if (ext && ext !== '.') {filters.unshift({name: '',extensions: [ext.match(/[a-zA-Z]+$/)[0]]})}dialog.showSaveDialog(win, {filters,defaultPath:args}).then( res => {if(res.filePath){filePath = res.filePathwebContents.downloadURL(args) // 注意这里必须是下载文件可访问路径。而不是存储路径}})})// vue页面中的逻辑 ***.vueimport { ipcRenderer } from "electron"// 触发var url = '下载地址.***'ipcRenderer.send('download', url)
执行完上面的代码会弹窗另存为下载,会发现下载没有显示进度的地方
2、监听下载开始、下载进度、下载结束
监听webContents中的will-download事件会返回下载相关的一些信息,这里把下载过程中的一些状态和用到的一些参数发送给webContents中打开的页面
// download.js 部分代码webContents.session.on('will-download', (event, item, webContents) => {item.setSavePath(filePath) // 这里是存储路径或者存储文件名称var filName = path.basename(filePath)win.webContents.send('win-will-download',{type:'start',params:{filName}})item.on('updated', (event, state) => {if (state === 'interrupted') {console.log('Download is interrupted but can be resumed')} else if (state === 'progressing') {if (item.isPaused()) {console.log('Download is paused')} else {win.webContents.send('win-will-download',{type:"progress",params:{totalBytes:item.getTotalBytes(),receivedBytes:item.getReceivedBytes()}})}}})item.once('done', (event, state) => {if (state === 'completed') {win.webContents.send('win-will-download',{type:"completed"})console.log('Download successfully')} else {console.log(`Download failed: ${state}`)}})})// ***.vue//download是展示下载进度的组件,下面会有相应的代码 这里通过ref创建响应数据 vue2的话可以通过 Vue.observable API进行创建
import download from "@/components/download/index.vue"
import { ElNotification } from 'element-plus'
import { h, ref } from 'vue'
var totalBytes = ref(0)
var receivedBytes = ref(0)mounted(){ipcRenderer.removeAllListeners('win-will-download')ipcRenderer.on('win-will-download', this.winDownLoadFun)},methods:{winDownLoadFun(event, data) {if (data.type == 'start') {this.notice && this.notice.close && this.notice.close()var progress = h(download, {totalBytes: totalBytes,receivedBytes: receivedBytes,filName: data.params.filName,onClose: () => {totalBytes.value = 0receivedBytes.value = 0this.notice && this.notice.close && this.notice.close()}})this.notice = ElNotification({title: '下载进度',position: 'bottom-right',duration: 0,showClose: false,message: progress,onClose: () => {this.notice = null}})}else if (data.type == 'progress') {totalBytes.value = data.params.totalBytesreceivedBytes.value = data.params.receivedBytes} else if (data.type == 'completed') {receivedBytes.value = totalBytes.value}},}
3、根据监听内容操作vnode展示加载进度
下面是download/index.vue完整文件
<template><div style="width: 100%;"><div><div @click="$emit('close')" v-if="percentage == 100" style="position: absolute;top: 15px;right: 15px;cursor: pointer;">关闭</div><div class="task-item"><img class="img" src="@/assets/image/zip-1.png"></img><div class="name"><div>{{filName}}</div><div class="progress1">{{limitFormat(receivedBytes.value)}}/{{limitFormat(totalBytes.value)}}</div></div></div><div><el-progress :show-text="false" :percentage="percentage" /></div></div></div>
</template><script>
import { ElMessage, ElProgress } from 'element-plus'
import { ref } from 'vue'
export default {name: 'download',props: {filName:{type:String,default:""},totalBytes: {default() {return ref(0)}},receivedBytes: {default() {return ref(0)}}},computed:{percentage(){return parseFloat((((this.receivedBytes.value / this.totalBytes.value) ||0 )* 100).toFixed(2)) }},watch:{percentage(){if(this.percentage == 100 && this.totalBytes.value != 0){ElMessage({message:"下载完成!",type:"success"})}},},methods: {limitFormat(limit) {var size = "";if (limit < 0.1 * 1024) { //小于0.1KB,则转化成Bsize = limit.toFixed(2) + "B"} else if (limit < 0.1 * 1024 * 1024) { //小于0.1MB,则转化成KBsize = (limit / 1024).toFixed(2) + "KB"} else if (limit < 0.1 * 1024 * 1024 * 1024) { //小于0.1GB,则转化成MBsize = (limit / (1024 * 1024)).toFixed(2) + "MB"} else { //其他转化成GBsize = (limit / (1024 * 1024 * 1024)).toFixed(2) + "GB"}var sizeStr = size + ""; //转成字符串var index = sizeStr.indexOf("."); //获取小数点处的索引var dou = sizeStr.substr(index + 1, 2) //获取小数点后两位的值if (dou == "00") { //判断后两位是否为00,如果是则删除00return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2)}return size;}},}
</script><style scoped>
.task-item {width: 280px;display: flex;align-items: center;margin-bottom: 6px;
}.progress1 {font-size: 12px;margin-top: -4px;color: #999;
}.task-item i {}.img {width: 32px;height: 32px;display: block;margin-right: 14px;}
</style>
download.js完整代码
const { ipcMain, dialog, shell } = require('electron')
const path = require('path')
const fs = require('fs');
const { type } = require('os');
exports.initDownload = function (win) {let filePath = '';// 监听渲染进程发出的download事件const webContents = win.webContents;ipcMain.on('download', (evt, args) => {const fileArr = args.split("/");let ext = path.extname(args)let filters = [{ name: '全部文件', extensions: ['*'] }]if (ext && ext !== '.') {filters.unshift({name: '',extensions: [ext.match(/[a-zA-Z]+$/)[0]]})}dialog.showSaveDialog(win, {filters,defaultPath:args}).then( res => {if(res.filePath){filePath = res.filePathwebContents.downloadURL(args) // 注意这里必须是下载文件可访问路径。而不是存储路径}})})webContents.session.on('will-download', (event, item, webContents) => {item.setSavePath(filePath) // 这里是存储路径或者存储文件名称var filName = path.basename(filePath)win.webContents.send('win-will-download',{type:'start',params:{filName}})item.on('updated', (event, state) => {if (state === 'interrupted') {console.log('Download is interrupted but can be resumed')} else if (state === 'progressing') {if (item.isPaused()) {console.log('Download is paused')} else {win.webContents.send('win-will-download',{type:"progress",params:{totalBytes:item.getTotalBytes(),receivedBytes:item.getReceivedBytes()}})}}})item.once('done', (event, state) => {if (state === 'completed') {win.webContents.send('win-will-download',{type:"completed"})console.log('Download successfully')} else {console.log(`Download failed: ${state}`)}})})
}
main.js中使用代码
这里的main.js是electron的主进程文件,不是vue相关的问题
const { BrowserWindow } = require("electron");
const {initDownload} = require('@/utils/download.js')
var win = null;
async function createWindow() {win = new BrowserWindow({// 创建相关的参数});// 为创建的win窗口绑定下载事件initDownload(win)
}
createWindow()
相关文章:
electron展示下载进度条
我们使用electron下载文件时,会发现不像浏览器一样会有地方展示下载进度,这导致下载一些大文件时不知道下载进度到哪里了 下面我们通过electron提供的will-download监听和element-plus中的ElNotification和ElProgress组件实现这一功能 实现逻辑 触发…...
Spark 基础操作
Spark 操作 创建操作(Creation Operation) 用于RDD创建工作。RDD创建只有两种方法,一种是来自于内存集合和外部存储系统,另一种是通过转换操作生成的RDD 转换操作(Transformation Operation) 将RDD通过一定的操作变成新的RDD,比如HadoopR…...
VoLTE 微案例:VoLTE 注册失败,I-CSCF 返回 403,HSS(UAR) 返回 5001
目录 1. 问题描述 2. 故障注册流程与正常流程对照 3. 结论 博主wx:yuanlai45_csdn 博主qq:2777137742 想要 深入学习 5GC IMS 等通信知识(加入 51学通信),或者想要 cpp 方向修改简历,模拟面试,学习指导都可以添加博主低价指导哈。 1. 问题描述...
智能财务 | 数据与融合,激发企业财务数智化转型思考
数据与融合,激发企业财务数智化转型思考 用友持续深耕企业财务领域,见证中国企业走过了财务电算化、信息化时代,当下共同经历数智化时代。2023 年度,通过走访标杆企业,与高校教授、权威机构学者共同探讨等形式…...
docker 下载netcore 镜像
dotnet-docker/README.runtime.md at main dotnet/dotnet-docker GitHub docker pull mcr.microsoft.com/dotnet/runtime:8.0 docker pull mcr.microsoft.com/dotnet/runtime:3.1...
Ajax:请求 响应
Ajax:请求 & 响应 AjaxjQuery的Ajax接口$.get$.post$.ajax PostMan 接口测试getpost Ajax 浏览器中看到的数据,并不是保存在浏览器本地的,而是实时向服务器进行请求的。当服务器接收到请求,就会发回一个响应,此时浏…...
WebForms DataList 控件深入解析
WebForms DataList 控件深入解析 概述 在 ASP.NET WebForms 的众多服务器控件中,DataList 控件是一个功能强大的数据绑定控件,它允许开发者以表格形式展示和操作数据。DataList 控件类似于 Repeater 控件,但提供了更多的内置布局和样式选项…...
【有啥问啥】DINO:一种改进的去噪锚框的端到端目标检测器
DINO:一种改进的去噪锚框的端到端目标检测器 在目标检测领域,DINO(DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection)是一种创新的端到端目标检测模型,旨在解决传统目标检测算法中的一些关…...
自由学习记录(15)
Java注解 else if的省略问题(可能看花) else if也是取最近的if连通,看上去加了{}就可以正常执行了,缩进要命,不提示真容易看错, 组合数公式和数组参数 在 C 中,数组作为函数参数时,…...
Docker 部署 JDK11 图文并茂简单易懂
部署 JDK11 ( Docker ) [Step 1] : 下载JDK11 - JDK 11 | Oracle 甲骨文官网 [Step 2] : jdk11上传服务器/root/jdk11 可自行创建文件夹 进入目录 /root/jdk11 解压文件 tar -zxvf jdk-11.0.22_linux-x64_bin.tar.gz解压后 进入 /root/jdk11/jdk-11.0.22 创建 jre 文件 ./bi…...
Cisco ASAv虚拟防火墙
EVE-NG模拟器使用Cisco防火墙版本ASAv-9.20.3-PLR-Licensed。配置如下,主要是三个方面,配置管理口地址模式DHCP,配置安全级别;第二,开启http服务器,配置允许访问主机的网段和接口;最后配置用户名…...
w~自动驾驶合集6
我自己的原文哦~ https://blog.51cto.com/whaosoft/12286744 #自动驾驶的技术发展路线 端到端自动驾驶 Recent Advancements in End-to-End Autonomous Driving using Deep Learning: A SurveyEnd-to-end Autonomous Driving: Challenges and Frontiers 在线高精地图 HDMa…...
C/C++ H264文件解析
C实现H264文件以及一段H264码流解析,源码如下: h264Parse.h: #ifndef _H264PARSE_H_ #define _H264PARSE_H_#include <fstream>class H264Parse { public:int open_file(const std::string &filename);/*** brief 从文件中读取一个nalu&…...
【Windows】电脑端口明明没有进程占用但显示端口被占用(动态端口)
TOC 一、问题 重启电脑后,启用某个服务显示1089端口被占用。 查看是哪个进程占用了: netstat -aon | findstr "1089"没有输出,但是换其他端口,是可以看到相关进程的: 现在最简单的方式是给我的服务指定另…...
Redis 持久化 问题
前言 相关系列 《Redis & 目录》(持续更新)《Redis & 持久化 & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Redis & 持久化 & 总结》(学习总结/最新最准/持续更新)《Redis & …...
vivado 配置
配置 配置指的是将特定应用数据加载到 FPGA 器件的内部存储器的进程。 赛灵思 FPGA 配置数据储存在 CMOS 配置锁存 (CCL) 中,因此配置数据很不稳定,且在每次 FPGA 器件上电后都必须重 新加载。 赛灵思 FPGA 器件可通过配置引脚,自行…...
Java如何实现PDF转高质量图片
大家好,我是 V 哥。在Java中,将PDF文件转换为高质量的图片可以使用不同的库,其中最常用的库之一是 Apache PDFBox。通过该库,你可以读取PDF文件,并将每一页转换为图像文件。为了提高图像的质量,你可以指定分…...
itemStyle.normal.label is deprecated, use label instead.
itemStyle.normal.label is deprecated, use label instead. normal’hierarchy in label has been removed since 4.0. All style properties are configured in label directly now. 错误写法: itemStyle: {normal: {// color: #00E0FF, // 设置折线点颜色 labe…...
如何在 Linux VPS 上保护 MySQL 和 MariaDB 数据库
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 有许多在 Linux 和类 Unix 系统上可用的 SQL 数据库语言实现。MySQL 和 MariaDB 是在服务器环境中部署关系型数据库的两个流行选项…...
CSS 样式 box-sizing: border-box; 用于控制元素的盒模型如何计算宽度和高度
文章目录 box-sizing: border-box; 的含义默认盒模型 (content-box)border-box 盒模型 在微信小程序中的应用示例 在微信小程序中,CSS 样式 box-sizing: border-box; 用于控制元素的盒模型如何计算宽度和高度。具体来说, box-sizing: border-box; 会改…...
RWKV7-1.5B-g1a多语言生成能力展示:中英日韩混合提示词真实输出效果对比
RWKV7-1.5B-g1a多语言生成能力展示:中英日韩混合提示词真实输出效果对比 1. 模型简介与核心能力 rwkv7-1.5B-g1a是基于新一代RWKV-7架构开发的多语言文本生成模型,特别优化了中英日韩四种语言的混合处理能力。这个1.5B参数的版本在保持轻量化的同时&am…...
个人开发者如何高效率APP上架安卓应用市场?软著、备案、资质、审核详解大全,一篇文章讲透流程规则!
一、上架前的资质准备 1. 软件著作权登记证书(软著) 软著是证明APP拥有自主知识产权的重要文件,多数应用商店要求上架时提供。申请周期通常为1-2个月,建议提前规划。 2. APP备案 根据工信部要求,APP主办者需要在接…...
LyricsX:macOS平台的多源歌词同步与显示技术方案
LyricsX:macOS平台的多源歌词同步与显示技术方案 【免费下载链接】LyricsX 🎶 Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX LyricsX是一款专为macOS设计的开源歌词应用,通过集成多个歌词源和…...
cutlass代码架构分析
CUTLASS 代码架构分析 本文档基于 cutlass代码进行梳理,快速理解 CUTLASS 4.x 的模块边界与调用链路。 1. 总体架构 CUTLASS 本质上是一个 header-only 的 CUDA C++ 模板库,外围配套了可选构建目标: include/:核心库(cutlass + cute) tools/:库实例化、性能测试与通用…...
OpenClaw调试技巧:nanobot镜像的日志分析与问题定位
OpenClaw调试技巧:nanobot镜像的日志分析与问题定位 1. 为什么需要关注OpenClaw日志 上周我在本地部署nanobot镜像时遇到一个诡异现象:OpenClaw能正常接收飞书消息,但执行自动化任务时总在"思考阶段"卡住。这个问题困扰了我两天&…...
OpenClaw与nanobot镜像结合:打造个人AI研究助手全流程
OpenClaw与nanobot镜像结合:打造个人AI研究助手全流程 1. 为什么需要个人AI研究助手? 作为一名经常需要阅读大量论文的研究者,我发现自己每天要重复处理许多机械性工作:在多个学术平台检索最新文献、下载PDF并分类存储、提取关键…...
6个高效突破内容访问限制的开源工具使用指南
6个高效突破内容访问限制的开源工具使用指南 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在信息爆炸的数字时代,优质内容常常被付费墙限制访问。本文将系统介绍基于开源…...
Android NDK开发从入门到实战:解锁应用性能的终极武器
引言 在Android应用开发领域,Java和Kotlin凭借其简洁的语法和强大的框架支持,成为了绝大多数开发者的首选。然而,当面对高性能计算、游戏引擎集成、硬件加速访问或核心算法保护等场景时,纯Java层的实现往往显得力不从心。这时&…...
测试用例设计-XMind
🚀 一、XMind 用例设计核心思路👉 和传统Excel不同,XMind强调:以“功能模块”为主干 以“用户场景”为分支 以“测试点”为叶子节点👉 本质结构:模块 → 场景 → 用例点 → 具体测试数据/预期📌…...
魔兽世界插件开发利器:wow_api技术架构与实战指南
魔兽世界插件开发利器:wow_api技术架构与实战指南 【免费下载链接】wow_api Documents of wow API -- 魔兽世界API资料以及宏工具 项目地址: https://gitcode.com/gh_mirrors/wo/wow_api 技术探索:从需求到架构的演进之路 魔兽世界插件开发生态长…...
