内容简介:项目里需要实现一个导出csv的功能,这是个老生常谈的需求,而且我们使用的是或者
问题描述
项目里需要实现一个导出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的实现中这个url最大限制为2MB 。
所以,当在Chrome下载的文件大小超过2MB chrome便会报这样的错误(其他浏览器这里不做讨论):
下载 失败-网络错误
这里2MB的大小可以在chromium源码中可以看到:
const size_t kMaxURLChars = 2 * 1024 * 1024;
...
if (!iter->ReadString(&s) || s.length() > url::kMaxURLChars) {
*p = GURL();
return false;
}
而关于2MB限制的问题在 chromium论坛在2010年就被人作为bug提出来 了,但是从2010年一直讨论到2019年也没有明显的改善。
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的导出了,但是 Blob对象有大小限制吗?
Good question !
我们在 chromium的说明文档 中可以看到一个表:
| 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 的 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Vue 前端导出后端返回的excel文件
- ASP.NET 开源导入导出库Magicodes.IE 导出Pdf教程
- MrDoc 0.5.0 版本发布,优化 EPUB 导出,新增 PDF 导出,支持自定义思维导图
- php 导出 excel
- oracle导出序列sequence
- vue导出excel表格
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
推荐系统
[奥地利] Dietmar Jannach、Markus Zanker、Alexander Felfernig、Gerhard Friedrich / 蒋 凡 / 人民邮电出版社 / 2013-6-25 / 59.00元
编辑推荐: 通过对本书的学习,读者不仅可以全面系统地了解该领域的基础原理,还能试验如何搭建一套真正的推荐系统。 —— 百度主任架构师、百度技术委员会主席 廖若雪 本书比较全面地介绍了推荐系统涉及的相关知识点,很适合对于推荐系统感兴趣的相关人员作为入门教程,目前能够系统全面介绍相关技术的中文书籍还显得匮乏,相信这本译著对于缓解这种情况大有裨益。 ——新浪微博数据挖掘技术专家 ......一起来看看 《推荐系统》 这本书的介绍吧!