博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Data URI Scheme优雅的实现前端导出csv
阅读量:5893 次
发布时间:2019-06-19

本文共 2214 字,大约阅读时间需要 7 分钟。

问题描述

项目里需要实现一个导出csv的功能,这是个老生常谈的需求,而且我们使用的是iview的组件库,按道理说实现起来应该简单,但实则不然,我在做的时候遇到了一些问题。受限于请求需要token后端分页接口性能等原因不得不放弃iview的导出方式。所以我需要寻找一种可行的、合理的、优雅的导出方案,那就是Data URI Scheme

方案实现

方案介绍

是利用HTML标签的hrefsrc属性来实现的。他看起来像是这样的:

Red dot

或者

download

按照这种方案的介绍,我们把要导出的数据拼接在href指定位置就能实现导出的需求,代码实现看起来像这样:

download
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会报这样的错误:

下载失败-网络错误

clipboard.png

后来google到这个限制是2MB,因为没有官方文档说明,感觉2MB的说法不是很确定,所以去扒了Chromium源码,找到了相关代码:

const size_t kMaxURLChars = 2 * 1024 * 1024;...if (!iter->ReadString(&s) || s.length() > url::kMaxURLChars) {    *p = GURL();    return false;}

2MB的限制算是实锤了,同时发现了,但是一直讨论到2019年也没有明显的改善(只是改了图片部分)。唉,chromium不改,我们能怎么办呢?

方案改进

chromium不改,那我们只能自己想办法了,于是有来突破这个限制。

借助对象和我们可以得到一个很短的、而且几乎与内容长度无关的URL:

blob:https://xxx.com/0bde569d-20a2-4085-95e6-dcec242962c6

这样就能突破Chrome对Data URI Scheme URL大小的限制了。

当然呢,我没用过URL.createObjectURL这个方法,也没用过Blob对象,所以我们要看看浏览的支持情况

clipboard.png

恩,看起来没有问题,那我们来看看代码实现。

download
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 !

我在中找到一个表:

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

iview的实现

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

参考文档

转载地址:http://gpisx.baihongyu.com/

你可能感兴趣的文章
[IOI2018]组合动作——构造
查看>>
BZOJ1430小猴打架——prufer序列
查看>>
浅谈IT路的职业规划
查看>>
Webtoos 仿Q+云桌面框架
查看>>
Liunx查找命令解析与分析
查看>>
jfinal3.0+easyui1.4.4后台权限管理系统 [2017.2.11 更新]
查看>>
centos7安装telnet服务
查看>>
iPhone、iPad的尺寸、分辨率
查看>>
JS函数表达式 -- 闭包
查看>>
安卓语音内录
查看>>
[Contest20180313]灵大会议
查看>>
[TCO2013]Block3Checkers
查看>>
undefined reference to 问题汇总及解决方法 ----- 还有一种问题没有解决(可能是顺序问题)...
查看>>
android复习第二天------布局
查看>>
表单根据不同的提交按钮转向不同的页面操作
查看>>
JAVA - Collections用法总结
查看>>
js数组方法总结
查看>>
实现“类似电梯”回到网页指定位置
查看>>
2019年6月多校联训b层——搜索算法 Problem A 宽搜 营救
查看>>
归并排序
查看>>