题目形貌
项目里须要完成一个导出csv的功用,这是个陈词滥调的需求,而且我们运用的是iview
的组件库,按道理说完成起来应当简朴,但实则不然,我在做的时刻遇到了一些题目。受限于要求须要token
、后端分页
、接口
、机能
等缘由不能不摒弃iview
的导出体式格局。所以我须要寻觅一种可行的、合理的、文雅的导出计划,那就是Data URI Scheme
。
计划完成
计划引见
Data URI Scheme是应用HTML标签的href
和src
属性来完成的。他看起来像是如许的:
<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会报如许的毛病:
下载
失利-收集毛病
厥后google到这个限定是2MB,由于没有官方文档申明,觉得2MB的说法不是很肯定,所以去扒了Chromium源码,找到了相干代码:
const size_t kMaxURLChars = 2 * 1024 * 1024;
...
if (!iter->ReadString(&s) || s.length() > url::kMaxURLChars) {
*p = GURL();
return false;
}
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
对象,所以我们要看看阅读的支撑状况
恩,看起来没有题目,那我们来看看代码完成。
<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的申明文档中找到一个表:
Device | Ram | In-Memory Limit | Disk | Disk Limit | Min Disk Availability |
---|---|---|---|---|---|
Cast | 512 MB | 102 MB | 0 | 0 | 0 |
Android Minimal | 512 MB | 5 MB | 8 GB | 491 MB | 10 MB |
Android Fat | 2 GB | 20 MB | 32 GB | 1.9 GB | 40 MB |
CrOS | 2 GB | 409 MB | 8 GB | 4 GB | 0.8 GB |
Desktop 32 | 3 GB | 614 MB | 500 GB | 50 GB | 1.2 GB |
Desktop 64 | 4 GB | 2 GB | 500 GB | 50 GB | 4 GB |
从这个表中,也许能够看出来在In-Memory Storage
的时刻桌面版64位Chrome Blob的上限为2GB(在Chrome 57上限是500MB)。所以现在看来这类要领应当是平安的。至此,这个题目算是完全的处理了。
iview的完成
别的,在我写这篇文章的时刻我发明iview
的export-csv
要领也是根据这个计划实行的,而且做了更多兼容,能够轻易人人参考。但他在资本开释的处所做的还需革新,也愿望人人注重。
参考文档
- Data protocol URL size limitations
- Excellent Export and the Chrome URL limit
- Data_URI_scheme
- excellentexport pull request
- 没法在nodejs中下载大文件
- Issue 69227: Loading large URLs kills the renderer
- Issue 375297: the total blobs’ size cannot exceed about 500MiB
- Is there any limitation on JavaScript Max Blob size
- chromium/url/url_param_traits.cc#L36
- chromium/url/url_constants.cc#L32
- iview 3.x export-csv