实现思路
- 框架特点
Electron在主进程的窗口中开启nodeIntegration后,可以直接在渲染进程中使用node.js来进行文件IO操作
- 断点下载
- 获取下载文件总大小 total_bytes
- 使用node读取已下载文件大小 received_bytes,在请求头中设置'range':'bytes=' +
${received_bytes}-${total_bytes}',服务端会返回'range'范围内的数据 - 使用request库请求下载url得到数据流,创建文件写入流并写入文件(注意:创建写入流时flags参数需要设置为'a',否则每次写入会覆盖之前已写入的数据)
- 暂停下载
将创建的请求request和写入流stream关闭,可使用end()或destroy()方法,具体使用详见node官方文档nodejs.org/docs/latest…
代码实现(Vue2)
// 获取下载文件大小
const axios = require('axios')
async getFileSize(url) {
return await axios
.head(url)
.then((res) => {
return res.headers['content-length']
})
.catch((err) => {
console.log(err)
})
},
// 下载文件(通过id实现多文件下载)
const fs = require('fs')
const request = require('request')
const progress = require('progress-stream')
export default {
data() {
return {
downloadList: {},
}
},
methods: {
downloadFile(total_bytes, path, url, id) {
let stream, requestItem
let received_bytes = 0
try {
// 获取已下载文件大小
let stats = fs.statSync(path)
if (total_bytes == stats.size) {
return
}
received_bytes = stats.size
} catch (err) {}
let params = {
method: 'GET',
url: url,
headers: {},
}
if (received_bytes > 0) {
params.headers['Range'] = 'bytes=' + `${received_bytes}-${total_bytes}`
}
stream = fs.createWriteStream(path, { flags: 'a' })
requestItem = request(params)
// 配合progress-stream库实现进度条功能
let req_progress = progress({
length: total_bytes,
time: 1500,
})
let req = requestItem.pipe(req_progress).pipe(stream)
this.$set(this.downloadList, id, {
request: req,
stream,
percentage: 0,
})
req_progress.on('progress', (progress) => {
const percentage = ((progress.transferred + received_bytes) / total_bytes) * 100
const downloadItem = this.downloadList[id]
if (downloadItem) {
this.$set(downloadItem, 'percentage', percentage)
}
})
req.on('close', () => {
const percentage = this.downloadList[id]?.percentage || 0
if (percentage == 100) {
console.log(id, '下载完毕!')
this.$delete(this.downloadList, id)
}
})
},
}
}
// 暂停下载
cancelInstall(id) {
this.downloadList[id].stream.end()
this.downloadList[id].request.end()
this.$delete(this.downloadList, id)
},