使用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 方法 也是按照这个方案实施的,而且做了更多兼容,可以方便大家参考。但他在资源释放的地方做的还需改进,也希望大家注意。

参考文档


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

查看所有标签

猜你喜欢:

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

Graph Algorithms

Graph Algorithms

Shimon Even / Cambridge University Press / 2011-9-19 / USD 32.99

Shimon Even's Graph Algorithms, published in 1979, was a seminal introductory book on algorithms read by everyone engaged in the field. This thoroughly revised second edition, with a foreword by Richa......一起来看看 《Graph Algorithms》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码