效果展示

项目背景:

由于浏览器的限制,web批量下载体验不好以及无法下载文件夹。采用Electron技术,通过js开发PC应用程序,着力解决批量下载、断点续传、文件夹下载等问题。配合网页版网盘使用,单个小文件使用浏览器内置下载,单个大文件、多文件、文件夹调用PC应用程序,提升下载体验。

技术栈

Electron项目的目的,是为了要避免使用 vue 手动建立起 electron 应用程序。electron-vue 充分利用 vue-cli 作为脚手架工具,加上拥有 vue-loader 的 webpackelectron-packager 或是 electron-builder,以及一些最常用的插件,如vue-routervuex 等等。

技术点分析

1、web、PC应用程序通信

官方描述:

app.setAsDefaultProtocolClient(protocol[, path, args])

  • protocol String - 协议的名称, 不包含 ://。 如果您希望应用程序处理 electron:// 的链接, 请将 electron 作为该方法的参数.
  • path String (可选) Windows -默认为 process.execPath
  • args String[] (可选) Windows - 默认为空数组

返回 Boolean -是否成功调用。

此方法将当前可执行文件设置为协议(也称为URI方案) 的默认处理程序。 它允许您将应用程序更深入地集成到操作系统中。 一旦注册成功, 所有 your-protocol:// 格式的链接都会使用你的程序打开。 整个链接 (包括协议) 将作为参数传递给您的应用程序。

在 Windows 系统中,你可以提供可选参数 path,可执行文件的路径和 args (在启动时传递给可执行文件的参数数组)

注意: 在 macOS 上, 您只能注册已添加到应用程序的 info. plist 中的协议, 在运行时不能对其进行修改。 但是,您可以在构建时使用简单的文本编辑器或脚本更改文件。 有关详细信息,请参阅 Apple's documentation

API 在内部使用 Windows 注册表和 LSSetDefaultHandlerForURLScheme。

获取参数:

主要分为两个阶段:一是初次启动应用,而是应用已启动打开链接时。

阶段一:

webContents渲染以及控制web页面,是BrowserWindow对象的一个属性。

Event:'did-finish-load'

导航完成时触发,即选项卡的旋转器将停止旋转,并指派 onload 事件后。

contents.on('did-finish-load', () => {
getPath().then(dir => {
setDir(dir)
fileList("DOWN_FILE_LIST_FLAG__804e62a93de9fda85bb6ca68b20d3d6d")
if(macOpenUrl != ''){//macOS
fileList(macOpenUrl)
}else{
try {
let str = process.argv.slice(1)[0].split('//')[1]
let downloadFlag = str.slice(0, str.length - 1)
fileList(downloadFlag)
} catch (e) { console.log(e) }
} let httpList = deepList('.cfg')
contents.send('download', httpList)
})
})

阶段二:

应用已启动时,用户打开URL。macOS有直接可捕捉的事件,Windows需要通过单实例的方法捕捉参数。

事件: 'open-url' macOS

返回:

  • event Event
  • url String

当用户想要在应用中打开一个 URL 时发出。 应用程序的 Info. plist 文件必须在 CFBundleURLTypes 项中定义 url 方案, 并将 NSPrincipalClass 设置为 AtomApplication 

如果你想处理这个事件,你应该调用 event.preventDefault() 。

app.on("open-url", function(event, url) {
//macOS:先进入open-url,再进入did-finish-load
let downloadFlag = url.split('//')[1]
macOpenUrl = downloadFlag
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
try {
fileList(downloadFlag)
} catch (e) { console.log(e) }
}
})

app.makeSingleInstance()

返回 Boolean

此方法使应用程序成为单个实例应用程序, 而不是允许应用程序的多个实例运行, 这将确保只有一个应用程序的实例正在运行, 其余的实例全部会被终止并退出。

const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
try {
//dialog.showErrorBox('makeSingleInstance', commandLine.toString())
let str = commandLine.slice(1)[0].split('//')[1]
let downloadFlag = str.slice(0, str.length - 1)
fileList(downloadFlag)
} catch (e) { console.log(e) }
}
})

URL长度限制问题:

基于项目背景,web、PC应用程序需要传递文件列表。一开始的想法是整个文件列表通过URL传递,后来调试的时候发现:受限于URL的长度限制,可以传递的文件项十分有限。于是另寻他路,通过后台中转:web选中文件后,调用后台接口,生成下载标识位,传递给PC应用程序。PC应用程序那边获取到下载标识位后,通过下载标识位再请求后台接口获取下载列表。

2、文件重命名算法

文件名的完整含义是文件的完整路径,如:D:/tmp/新建文件夹/002.docx。文件重命名有两个场景:一是当前的文件列表内,如果存在同名的文件,需要对当前的文件重命名,算法同windows文件重命名算法。二是文件保存到本地路径时,如果当前路径存在同名的文件,需要对当前的文件重命名,算法同windows文件重命名算法。

方法:fireRename(arr, basename, key)

  • arr Arrary - 文件列表
  • basename String 当前文件的文件名
  • key String(可选) 文件列表内每个对象文件名的关键字

文件重命名,返回重命名后的文件名。

const fileRename = (arr, basename, key) => {
let existed
arr.forEach((e, i) => {
if (e[key] == basename) {
existed = true
}
})
if (!existed) {
return basename
}
let extname = path.extname(basename)
let re = new RegExp('(\\(\\d\\))*' + extname + '$')
const compare = (c, b) => {
return c.replace(re, '') == b.replace(re, '')
}
let arr_existed = []
arr.forEach((e, i) => {
let c = e[key] if (compare(c, basename)) {
arr_existed.push(e[key].replace(c.replace(re, ''), ''))
}
}) for (let i = 1; i < arr_existed.length + 2; i += 1) {
if (arr_existed.indexOf('(' + i + ')' + extname) == -1) {
return basename.replace(re, '(' + i + ')' + extname)
}
}
}

用Electron开发企业网盘(一)--通信的更多相关文章

  1. 用Electron开发企业网盘(二)--分片下载

    书接上文,背景见:https://www.cnblogs.com/shawnyung/p/10060119.html HTTP请求头  Range 请求资源的部分内容(不包括响应头的大小),单位是by ...

  2. 联想企业网盘:SaaS服务集群化持续交付实践

    1      前言 当代信息技术飞速发展,软件和系统的代码规模都变得越来越大,而且组件众多,依赖繁复,每次新版本的发布都仿佛是乘坐一次无座的绿皮车长途夜行,疲惫不堪.软件交付是一个复杂的工程,涉及到软 ...

  3. 【Electron】Electron开发入门

    Electron简介: Electron提供了丰富的本地(操作系统)的API,使你能够使用纯JavaScript来创建桌面应用程序,并且跨平台(win,mac,linux等各种PC端平台).与其它各种 ...

  4. [实战]MVC5+EF6+MySql企业网盘实战(8)——文件下载、删除

    写在前面 上篇文章通过iframe实现了文件的无刷新上传.这篇我们将实现文件的下载与删除. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySq ...

  5. electron 开发拆坑总结

    electron 总结 前言 有一个web项目需要用客户端来包装一下 项目的主要业务都在服务器上 所以项目的大多数功能都用url 地址来访问: 客户端登陆界面在本地 打包客户端的本地登陆界面 做为登陆 ...

  6. Electron开发跨平台桌面程序入门教程

    最近一直在学习 Electron 开发桌面应用程序,在尝试了 java swing 和 FXjava 后,感叹还是 Electron 开发桌面应用上手最快.我会在这一篇文章中实现一个HelloWord ...

  7. 使用electron开发桌面级小程序自动部署系统

    那一天我二十一岁,在我一生的黄金时代,我有好多奢望.我想爱,想吃,还想在一瞬间变成天上半明半暗的云,后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消逝,最后变得像挨了锤的牛一样. ...

  8. Electron-使用Electron开发第一个应用

    使用Electron开发第一个应用 Electron 应用的目录结构如下: app/ ├── package.json ├── main.js └── index.html 新建一个app文件夹 将这 ...

  9. [实战]MVC5+EF6+MySql企业网盘实战(28)——其他列表

    写在前面 本篇文章将实现,其他文件类型的列表. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企业网盘实战(1) [实战]MVC5+EF ...

随机推荐

  1. Linux就该这么学 20181005(第九章SSH远程对话)

    参考链接https://www.linuxprobe.com/ nmtui开启网卡设置 ONBOOT=yes systemctl restart network nmcli connection sh ...

  2. 移动端 input 获取焦点后弹出带enter(类似于搜索,确定,前往)键盘,以及隐藏系统键盘

    一:调出系统带回车键的键盘 在项目中经常有输入框,当输入完成后点击确定执行相应的动作.但是有些设计没有确定或者搜索按钮,这就需要调用系统键盘,点击系统键盘的确定后执行相应动作. 但是单纯的input是 ...

  3. [nginx]第一篇

    世界太大,我无法安心学习,决定看一个简单的. nginx-1.11.9的代码是nginx-0.5.38的两倍,决定看前者的. 阅读工具:UnderStand 3.1. 入口在nginx.c的195行. ...

  4. (转载)Android之有效防止按钮多次重复点击的方法(必看篇)

    为了防止测试妹子或者用户频繁点击某个按钮,导致程序在短时间内进行多次数据提交or数据处理,那到时候就比较坑了~ 那么如何有效避免这种情况的发生呢? 我的想法是,判断用户点击按钮间隔时间,如果间隔时间太 ...

  5. Servlet学习(四)——response

    1.概述 在创建Servlet时会覆盖service()方法,或doGet()或doPost(),这些方法都有两个参数,一个是代表请求的request和代表响应response. service方法中 ...

  6. 【原创】rman备份出现ORA-19625

    [oracle@sunny stage]$ rman target / Recovery Manager: Release 10.2.0.1.0 - Production on Sun Mar 18 ...

  7. linux查看系统cpu信息

    # 查看物理CPU个数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l # 查看每个物理CPU中core的个数(即 ...

  8. 【BZOJ4448】【SCOI2015】情报传递

    这题面错别字真tm多 题意: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有若T名(可能没有)下线,除1名大头日外其余n-1 ...

  9. [POJ2823][洛谷P1886]滑动窗口 Sliding Window

    题目大意:有一列数,和一个窗口,一次能框连续的s个数,初始时窗口在左端,不断往右移动,移到最右端为止,求每次被框住的s个数中的最小数和最大数. 解题思路:这道题是一道区间查询问题,可以用线段树做.每个 ...

  10. react-native 编译 undefined is not an object (evaluating '_react2.PropTypes.func')

    情况通报: 因为是我的二维码模块报错,提示报错代码如下 重要信息是下面的红色字体部分(Android 模拟器红屏) undefined is not an object (evaluating '_r ...