纯前端实现包含 Excel 的 Zip 压缩包导出

通过 html + js 、Vue 两种方式,实现纯前端实现包含 Excel 的 Zip 压缩包导出。

相关依赖

SheetJS

  • GitHub:https://github.com/SheetJS/sheetjs
  • 官网:https://sheetjs.com/
  • 下载:https://www.cdnpkg.com/xlsx/file/xlsx.core.min.js/?id=78603
  • npmjs:https://www.npmjs.com/package/sheetjs

JSZip

  • GitHub:https://github.com/Stuk/jszip/
  • 官网:https://stuk.github.io/jszip/
  • npmjs:https://www.npmjs.com/package/jszip

FileSaver

  • GitHub:https://github.com/eligrey/FileSaver.js
  • 介绍:https://eligrey.com/blog/saving-generated-files-on-the-client-side/
  • npmjs:https://www.npmjs.com/package/file-saver

HTML+JS 导出

依赖下载

  • https://github.com/SheetJS/sheetjs/tree/master/dist
  • https://github.com/eligrey/FileSaver.js/tree/master/dist
  • https://github.com/Stuk/jszip/tree/master/dist

导入依赖

<script src="/js/jszip.min.js"></script>
<script src="/js/FileSaver.min.js"></script>
<script src="/js/xlsx.core.min.js"></script>

下载方法

function batchDownload(){
    var idArr = new Array();
    $.each($('input:checkbox:checked'),function(){
        var id = $(this).val();
        idArr.push(id);
    });
    if(idArr.length==0){
        alert("未选中任何数据,请先进行选择!");
        return;
    }
    var zip = new JSZip()
    for (var i = 0; i < idArr.length; i++) {
      var id = idArr[i]
      var wb = workbookData(id)
      var file_name = id+'-查询结果.xlsx'
      zip.file(file_name, workbook2blob(wb), { binary: true })
    }
    zip.generateAsync({type:"blob"}).then(content => {
      //生成zip文件包
      saveAs(content, '批量下载.zip')
    })
}

导出方法

function workbookData(id){
     var wb = XLSX.utils.book_new();
     var accountRes;
     $.ajax({
     	type: "POST",
     	url: "getResult",
     	data: {"id":id},
     	dataType: 'json',
     	async: false,
     	success: function(info){
     		accountRes = info.data;
     	}
     });
     var sheetData1 = accountRes.map(item => ({
         'id': item.id,
         '数据类型': item.data_type,
         '内容': item.content,
     }));
     var sheet1 = XLSX.utils.json_to_sheet(sheetData1);
     var wb = XLSX.utils.book_new();
     XLSX.utils.book_append_sheet(wb, sheet1, '查询结果');
     return wb;
 }

其他方法

将 workbook 装化成 blob 对象:

function workbook2blob(workbook) {
  // 生成excel的配置项
  var wopts = {
      // 要生成的文件类型
      bookType: "xlsx",
      // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
      bookSST: false,
      type: "binary"
  };
  var wbout = XLSX.write(workbook, wopts);
  // 将字符串转ArrayBuffer

  var blob = new Blob([s2ab(wbout)], {
      type: "application/octet-stream"
  });
  return blob;
}
function s2ab(s) {
  var buf = new ArrayBuffer(s.length);
  var view = new Uint8Array(buf);
  for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
  return buf;
}

Vue 导出

安装依赖

npm install xlsx --save
npm install jszip --save
npm install file-saver --save

引入依赖

在组件中导入 xlsx

import XLSX from 'xlsx';
import JSZip from 'jszip'
import FileSaver from 'file-saver'

增加按钮

实现多选非常简单:手动添加一个 el-table-column,设 type 属性为 selection 即可

<el-button size="small" type="success" icon="el-icon-circle-plus-outline" @click="batchDownload" >批量下载</el-button>

<el-table
          border
          size="small"
          v-loading="loading"
          stripe
          :data="analysisTaskData"
          style="width: 100%;"
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="50"></el-table-column>
          <el-table-column prop="id" label="ID" width="50"></el-table-column>
          <el-table-column prop="type" label="类型"></el-table-column>
</el-table>

对应方法

export default {
  data() {
    return {
      multipleSelection: []
    };
  },
  methods: {
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    async batchDownload(){
      console.log(this.multipleSelection)
      this.$message.success("批量下载成功!");
    }
  }
}

下载方法

async batchDownload(){
  const zip = new JSZip()
  for (var i = 0; i < this.multipleSelection.length; i++) {
    const id = this.multipleSelection[i].id
    const wb = await this.workbookData(id)
    const file_name = this.multipleSelection[i].content+'-任务结果('+id+').xlsx'
    zip.file(file_name, this.workbook2blob(wb), { binary: true })
  }
  let zipName = '批量下载'
  zip.generateAsync({type:"blob"}).then(content => { 
    //生成zip文件包
    FileSaver.saveAs(content, `${zipName}.zip`)
    this.$message.success("批量下载成功!");
  })
}

导出方法

async workbookData(id){
    const wb = XLSX.utils.book_new();
    const { data: res } = await this.$http.get("analysisTask/edit/" + id);
    if (res.code == 200) {
        this.res_type = res.data.res_type;
        const accountRes = JSON.parse(res.data.account_res);
        const tradeRes = JSON.parse(res.data.trade_res);
        const operationRes = JSON.parse(res.data.operation_res);
        const sheetData1 = accountRes.map(item => ({
            '登录帐号': item.mainAccount,
            '手机': item.phone,
            '邮箱': item.email,
        }));
        const sheetData2 = tradeRes.map(item => ({
            '登录帐号': item.mainAccount,
            '手机': item.phone,
            '邮箱': item.email,
        }));
        const sheetData3 = operationRes.map(item => ({
            '登录帐号': item.mainAccount,
            '手机': item.phone,
            '邮箱': item.email,
        }));
        const sheet1 = XLSX.utils.json_to_sheet(sheetData1);
        const sheet2 = XLSX.utils.json_to_sheet(sheetData2);
        const sheet3 = XLSX.utils.json_to_sheet(sheetData3);
        const wb = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(wb, sheet1, '账户信息1');
        XLSX.utils.book_append_sheet(wb, sheet2, '账户信息2');
        XLSX.utils.book_append_sheet(wb, sheet3, '账户信息3');
    } else {
        this.$message.error("获取Excel数据失败:" + res.msg);
    }
    return wb;
},

其他函数

将 blob 对象创建 bloburl,然后用 a 标签实现弹出下载框:

openDownloadDialog(blob, fileName) {
    if (typeof blob == "object" && blob instanceof Blob) {
        blob = URL.createObjectURL(blob); // 创建blob地址
    }
    var aLink = document.createElement("a");
    aLink.href = blob;
    // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,有时候 file:///模式下不会生效
    aLink.download = fileName || "";
    var event;
    if (window.MouseEvent) event = new MouseEvent("click");
    //   移动端
    else {
        event = document.createEvent("MouseEvents");
        event.initMouseEvent( "click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null );
    }
    aLink.dispatchEvent(event);
},

将 workbook 装化成 blob 对象:

workbook2blob(workbook){
    // 生成excel的配置项
    var wopts = {
        // 要生成的文件类型
        bookType: "xlsx",
        // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
        bookSST: false,
        type: "binary"
    };
    var wbout = XLSX.write(workbook, wopts);
    // 将字符串转ArrayBuffer

    var blob = new Blob([this.s2ab(wbout)], {
        type: "application/octet-stream"
    });
    return blob;
},
s2ab(s) {
   var buf = new ArrayBuffer(s.length);
   var view = new Uint8Array(buf);
   for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
   return buf;
},