使用Data URI Scheme优雅的实现前端导出csv

栏目: 编程语言 · 发布时间: 5年前

内容简介:项目里需要实现一个导出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的实现中这个url最大限制为2MB

所以,当在Chrome下载的文件大小超过2MB chrome便会报这样的错误(其他浏览器这里不做讨论):

下载
失败-网络错误

使用Data URI Scheme优雅的实现前端导出csv

这里2MB的大小可以在chromium源码中可以看到:

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

而关于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 对象,所以我们要看看浏览的支持情况

使用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的导出了,但是 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 )。所以从现在看来这种方法应该是安全的。至此,这个问题算是完整的解决了。

另外,在我写这篇文章的时候我发现 iviewexport-csv 方法 也是按照这个方案实施的,而且做了更多兼容,可以方便大家参考。但他在资源释放的地方做的还需改进,也希望大家注意。

参考文档


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Caching

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》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器