Electron-vue开发实战 - 文件下载及进度显示

761 阅读2分钟

主要通过 Electronwill-download 事件和主进程和渲染进程之间的通信,实时监听下载进度

main/index.js

mainWindow.webContents.session.on('will-download', (e, item) => {
    //获取文件的总大小
    const totalBytes = item.getTotalBytes();
    //设置文件的保存路径,此时默认弹出的 save dialog 将被覆盖
    const rootPath = app.getPath("userData") + "/channel";
    const filePath = path.join(rootPath, item.getFilename());
    item.setSavePath(filePath);
  	//获得下载链接
    let url = item.getURL()

    //监听下载过程,计算并设置进度条进度
    item.on('updated', () => {
      let process = item.getReceivedBytes() / totalBytes
      process = Math.round(process * 100)
      mainWindow.setProgressBar(process);
      //向渲染进程发送下载进度
      sendMessage(url, process)
    });
    //监听下载结束事件
    item.on('done', (e, state) => {
      //如果窗口还在的话,去掉进度条
      if (!mainWindow.isDestroyed()) {
        mainWindow.setProgressBar(-1);
      }

      //下载被取消或中断了
      if (state == 'interrupted') {
        electron.dialog.showErrorBox('下载失败', `文件 ${item.getFilename()} 因为某些原因被中断下载`);
      }
      if (state == 'completed') {
        //下载完成向渲染进程发送完成信号
        sendMessage(url + ':done', 'done')
      }
    });
  });

//向渲染进程发送信息
function sendMessage(url, text) {
  mainWindow.webContents.send(url, text);
}

渲染进程

<template>
  <el-table :data="updateDatas">
        <el-table-column property="name" label="应用名" width="100px"></el-table-column>
        <el-table-column property="url" label="下载链接"></el-table-column>
        <el-table-column align="center" width="140px">
          <template slot="header">
            状态
          </template>
          <template slot-scope="scope">
            <a
              :href="scope.row.url"
              @click="startDownload(scope.row,scope.$index)"
              v-if="!scope.row.progress"
            >
              <el-button size="mini" type="danger">下载</el-button>
            </a>
            <el-button size="mini" type="success" v-if="scope.row.progress==100">完成</el-button>
            <div
              class="progress-bar"
              :style="'width:' +scope.row.progress+'%'"
              v-if="scope.row.progress && scope.row.progress!=100"
            ></div>
          </template>
        </el-table-column>
      </el-table>
</template>

<script>
import { ipcRenderer } from "electron";
const axios = require("axios");

export default {
  data() {
    return {
      updateDatas: [],
      downloadState: 0
    };
  },
  methods: {
    startDownload(row, index) {
      this.downloadState += 1;
      //监听下载进程
      ipcRenderer.on(row.url, (event, progress) => {
        if (progress) {
          this.$set(this.updateDatas[index], "progress", progress);
        }
      });
      ipcRenderer.on(row.url + ":done", (event, state) => {
        if (state == "done") {
          this.downloadState -= 1;
          console.log(row.url + "done");
        }
      });
    }
  },
  watch: {
    downloadState: function() {
      if (this.downloadState == 0) {
        this.$message.success("全部下载完成,重新加载中,请稍等");
        this.downloadUrlVisible = false;
        this.$emit("refresh");
      }
    }
  },
  //生命周期 - 创建完成(访问当前this实例)
  created() {
    this.init();
  },
  //生命周期 - 挂载完成(访问DOM元素)
  mounted() {}
};
</script>
<style scoped>
.progress {
  margin-top: 2px;
  width: 200px;
  height: 14px;
  margin-bottom: 10px;
  overflow: hidden;
  background-color: #f5f5f5;
  border-radius: 4px;
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.progress-bar {
  background-color: rgb(92, 184, 92);
  background-image: linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.14902) 25%,
    transparent 25%,
    transparent 50%,
    rgba(255, 255, 255, 0.14902) 50%,
    rgba(255, 255, 255, 0.14902) 75%,
    transparent 75%,
    transparent
  );
  background-size: 40px 40px;
  box-shadow: rgba(0, 0, 0, 0.14902) 0px -1px 0px 0px inset;
  box-sizing: border-box;
  color: rgb(255, 255, 255);
  display: block;
  float: left;
  font-size: 12px;
  height: 16px;
  line-height: 20px;
  text-align: center;
  transition-delay: 0s;
  transition-duration: 0.6s;
  transition-property: width;
  transition-timing-function: ease;
  width: 266.188px;
}
</style>

实例

  1. 界面

2. 下载

3. 完成

参考链接

Electron APP 支持应用内下载文件及显示下载进度