纯前端导出excel

138 阅读2分钟

一、背景

遇到到动态表单+导出的场景, 后端不愿意为动态表单写导出, 于是只能前端做了

二、实现

1. 如何纯前端导出文件

实现原理还是通过a标签去下载和导出。
一般情况下,a标签的href属性,仅支持同源的绝对路径、相对路径和锚链接,当a标签具有download属性后,则href可以支持Data URLBlob URL,并提供下载

2. 如何导出excel

在创建Data URLBlob URL,我们可以设置其的数据类型和编码

Data URL

data URI scheme(数据URI方案)是URI(统一资源标识符)方案。目的是将一些小的数据。直接嵌入到网页中,从而不用再从外部文件加载。

data:[<media type>],<data>
  • data 表示方案名称
  • <media type> 表示媒体类型, 可以有多个参数, 通过分号分隔, 比如我们可以用来指定字符集 charset;数据的的mime类型;以及数据编码格式等
    data:[<mime type>][;charset=<charset>][;<encoding>], <encoded data>
    
    • [<mime type>] 可选项, 数据类型(如image/png、text/plain等)
    • [;charset=<charset>] 可选项,源文本的字符集编码方式(如utf-8)
    • [;<encoding>], 数据编码方式(US-ASCII,BASE64两种), 默认US-ASCII
    • <encoded data> 即编码后的数据, 如果不是[;<encoding>]方式编码后的数据,会报异常
  • <data> 即上面的<encoded data>

示例:

data:,文本数据

data:image/png;base64,base64编码的png图片数据

data:text/csv;charset=utf-8,表格文本数据

下载

interface DataSourceNode {
  [propsString: string]: string | number;
}
interface Column extends DataSourceNode {
  title: string; // 中文名
  dataIndex: string; // 英文名
}

/**
 * 导出excel
 * @param dataSource 数据源
 * @param columns 表格列配置
 * @param name 导出文件名
 */
export function exportToExcel(dataSource: DataSourceNode[], columns: Column[], name = '出.csv'){
  // 表头
  let str = `${columns.map((item) => item.title).join(',')}\n`;
  //增加\t为了不让表格显示科学计数法或者其他格式
  for (let i = 0; i < dataSource.length; i++) {
    for (let j = 0; j < columns.length; j++) {
      const key = dataSource[j].dataIndex;
      str += `${dataSource[i][key] + '\t'},`;
    }
    str += '\n';
  }
  // 添加data:前缀、数据类型、字符集编码方式
  // \ufeff 用于给数据添加BOM头,避免excel解析出错
  // encodeURIComponent处理中文和上面的特殊字符
  const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
  //通过创建a标签实现
  const link = document.createElement('a');
  link.href = uri;
  //对下载的文件命名
  link.download = name;
  link.click();
}

Blob URL

一些较老的chrome可能不支持Data URL, 这时我们也可以使用Blob来解决

Blob 对象表示一个不可变、原始数据的类文件对象

我们可以通过创建一个Blob对象,并获取其地址即 Blob URL,再将其地址赋值给href,用于下载

 ...
 // 创建blob对象
 const blob = new Blob([`\ufeff${str}`], {type: 'text/csv,charset=UTF-8'}
 // 获取blob url
 const uri = URL.createObjectURL(blob);
 
 link.href = uri;
 ...

三、总结

本文主要介绍了通过Data URLBlob URL和a标签的download属性纯前端下载excel文件,其它文件也可以通过这种方式来下载。

文中若有错漏或者可深入、优化之处, 望请不吝赐教