内容简介:项目里需要实现一个导出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表格
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Caching
Duane Wessels / O'Reilly Media, Inc. / 2001-6 / 39.95美元
On the World Wide Web, speed and efficiency are vital. Users have little patience for slow web pages, while network administrators want to make the most of their available bandwidth. A properly design......一起来看看 《Web Caching》 这本书的介绍吧!