运用Data URI Scheme文雅的完成前端导出csv

题目形貌

项目里须要完成一个导出csv的功用,这是个陈词滥调的需求,而且我们运用的是iview的组件库,按道理说完成起来应当简朴,但实则不然,我在做的时刻遇到了一些题目。受限于要求须要token后端分页接口机能等缘由不能不摒弃iview的导出体式格局。所以我须要寻觅一种可行的、合理的、文雅的导出计划,那就是Data URI Scheme

计划完成

计划引见

Data URI Scheme是应用HTML标签的hrefsrc属性来完成的。他看起来像是如许的:

<img src="data:image/png;base64,iVBORw0KGgoAAA
ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU
5ErkJggg==" alt="Red dot" />

或许

<a href="data:text/csv,something">download</a>

根据这类计划的引见,我们把要导出的数据拼接在href指定位置就能够完成导出的需求,代码完成看起来像如许:

<a href="" download="export.csv" id="export_csv" style="display='none'">download</a>
function export_csv (data) {
    $('#export_csv').href = 'data:attachment/csv,' + encodeURI(data);
    $('#export_csv').click();
    setTimeout(function () {
        $('#export_csv').href = '';    
    })
}
export_csv(csv_data_str);

测试发明,妥妥的,没缺点。

存在题目

在实践中这个计划是有限定的、不平安的:在chrome的完成中Data URI Scheme许可的URL的最大限定为2MB(其他阅读器这里不做议论)。
一开始并不知道是凌驾2MB才会出题目,只是发明:
当在下载的文件比较大(凌驾2.7MB)的时刻Chrome会报如许的毛病:

下载
失利-收集毛病

《运用Data URI Scheme文雅的完成前端导出csv》

厥后google到这个限定是2MB,由于没有官方文档申明,觉得2MB的说法不是很肯定,所以去扒了Chromium源码,找到了相干代码:

const size_t kMaxURLChars = 2 * 1024 * 1024;
...
if (!iter->ReadString(&s) || s.length() > url::kMaxURLChars) {
    *p = GURL();
    return false;
}
  1. 变量声明部份源码链接
  2. 变量援用部份源码链接

2MB的限定算是实锤了,同时发明2010年就有人在Chromium论坛提出2MB太小了了,然则一向议论到2019年也没有显著的改良(只是改了图片部份)。唉,chromium不改,我们能怎么办呢?

计划革新

chromium不改,那我们只能本身想办法了,因而有大牛提出来运用URL.createObjectURL + Blob来打破这个限定。
借助Blob对象和URL.createObjectURL我们能够获得一个很短的、而且险些与内容长度无关的URL:

blob:https://xxx.com/0bde569d-20a2-4085-95e6-dcec242962c6

如许就能够打破Chrome对Data URI Scheme URL大小的限定了。
固然呢,我没用过URL.createObjectURL这个要领,也没用过Blob对象,所以我们要看看阅读的支撑状况

《运用Data URI Scheme文雅的完成前端导出csv》

恩,看起来没有题目,那我们来看看代码完成。

<a href="" download="export.csv" id="export_csv" style="display='none'">download</a>
function export_csv (data) {
    const BOM = '\uFEFF';
    let blob_obj = new Blob([BOM + data], {type: 'text/csv'});
    let download_url = URL.createObjectURL(blob_obj);
    $('#export_csv').href = download_url;
    $('#export_csv').click();
    setTimeout(function () {
        // 经由过程createObjectURL建立的url须要经由过程revokeObjectURL()来开释
        URL.revokeObjectURL(download_url);
        $('#export_csv').href = '';
    })
}
export_csv(csv_data_str);

云云,题目处理了,如许就不怕凌驾2MB的CSV的导出了。

然则Chrome对Blob对象的大小有限定吗?

Good question !

我在chromium Blob的申明文档中找到一个表:

DeviceRamIn-Memory LimitDiskDisk LimitMin Disk Availability
Cast512 MB102 MB000
Android Minimal512 MB5 MB8 GB491 MB10 MB
Android Fat2 GB20 MB32 GB1.9 GB40 MB
CrOS2 GB409 MB8 GB4 GB0.8 GB
Desktop 323 GB614 MB500 GB50 GB1.2 GB
Desktop 644 GB2 GB500 GB50 GB4 GB

从这个表中,也许能够看出来在In-Memory Storage的时刻桌面版64位Chrome Blob的上限为2GB(在Chrome 57上限是500MB)。所以现在看来这类要领应当是平安的。至此,这个题目算是完全的处理了。

iview的完成

别的,在我写这篇文章的时刻我发明iviewexport-csv要领也是根据这个计划实行的,而且做了更多兼容,能够轻易人人参考。但他在资本开释的处所做的还需革新,也愿望人人注重。

参考文档

    原文作者:aqiongbei
    原文地址: https://segmentfault.com/a/1190000018181932
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞