声明
本人也在不断的学习和积累中,文章中有不足和误导的地方还请见谅,可以给我留言指正。希望和大家共同进步,共建和谐学习环境。
技术栈
Electron 16.2.8 + vue3.2.33 + ts
问题描述
-
需求
公司要求在桌面应用中实现一个下载中心(下载中心的代码后面我再贴出来),可以下载文件存储上的文件,也可以下载第三方页面上的文件。
-
原理
在渲染进程BrowserView中,如果触发了下载,我就拦截住浏览器的默认下载动作,然后在下载中心的界面我通过request
的方法再次请求下载地址进行下载。到此为止一切正常。
-
问题
第三方的没有问题,问题出现在自己的文件存储上面,我会得到文件的存储地址,然后通过contents.downloadURL(url)
的方式下载,然后再触发默认下载事件,后面的逻辑和上面的一样,但是在下载中心界面,就会报419。如果文件地址直接发在BrowserView中就可以正常下载。
解决
1、先查查419 是什么问题
419 - 认证超时:
并不是HTTP标注的一部分,419认证超时表示以前的有效证明已经失效了。同时也被用于401未认证的替代选择为了从其它被拒绝访问的已认证客户端中指定服务器的资源
2、尝试解决
- 增加请求的超时时间(无用)
- 考虑到可能是主进程和渲染进程之间的通讯上的消耗导致的,所以直接将主进程中的下载操作调整到渲染进程中。(无用)
- 最后打断点定位到,居然是fs 模块的方法阻塞造成的
3、修改方案
- 减少公用对象的重复创建
- 将关键位置的调用方法使用try catch 包裹,出现错误时,将错误的写入保存,后期再尝试调用
-
fs.createWriteStream
增加配置autoClose: true
和highWaterMark
属性(这是安全线,默认写的水位线是16k,即16 * 1024。表示总共写入的大小在这个范围内表示安全的,因为这代表着链表缓存区的大小)