出于安全考虑,JS无法直接调用FileAPI写文件到磁盘,但是却可以通过下载来变相实现保存功能。
JS要实现下载功能,一般都是这么几个过程:生成下载的URL,动态创建一个A标签,并将其href指向生成的URL,然后触发A标签的单击事件,这样就会弹出下载对话框,从而实现了一个下载的功能。
HTML5的download属性
这个属性很重要,它可以指定下载文件名,并且可以告诉浏览器目标链接是一个下载链接,不是一个普通链接,我们看下面代码就能看出区别了:
<a href="data:text/txt;charset=utf-8,测试下载纯文本" rel="external nofollow" rel="external nofollow" rel="external nofollow" download="测试.txt" >下载1</a>
<a href="data:text/txt;charset=utf-8,测试下载纯文本" rel="external nofollow" rel="external nofollow" rel="external nofollow" >下载2</a>
可以发现,下载1按钮能够实现下载,点击下载2链接时直接在浏览器打开文件内容了。
JS生成CSV文件并下载
csv是一种逗号分隔的表格文件格式,可以很好的被Excel支持,由于其文件格式简单,所以经常用在简单的表格上面。最重要的是它是一种纯文本格式,可以很轻松地用JS来生成而不借助第三方库。
不考虑兼容性的保存CSV方法:
/**
* 保存CSV文件
* @params csv csv文件内容
* @params saveName 保存的文件名
*/
function saveCSV(csv, saveName){
var a = document.createElement('a');
a.href = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(csv);
a.download = saveName;
a.click();
}
虽然我们用的是UTF-8编码,下载后你会发现,用文本编辑器打开没问题,但是用Excel打开乱码:
原因就是少了一个ufeffBOM头,所以在data里面添加一个\ufeff
解决了
文字换行问题
文字换csv的最大问题就是如何处理换行,很简单,使用`\n`,`\r`后再用encodeURIComponent编码一下就可以了。
大部分浏览器可能都没啥问题,但是一些比较老的Chrome可能下载的时候指定的download就是不生效,此时可以用blob来解决:(测试此方法测试在微软Edge
浏览器和IE11下都无法下载)
考虑兼容性的保存CSV方法:
/**
* 保存CSV文件
* @params csv csv文件内容
* @params saveName 保存的文件名
*/
function saveCSV(csv, saveName)
{
var blob = new Blob(['\ufeff' + csv], {type: 'text/csv,charset=UTF-8'});
openDownloadDialog(blob, saveName);
}
此方法测试在微软Edge
浏览器可以实现下载,但是在IE11下还是无法下载
封装下载函数
const openDownloadDialog = (url, saveName) => {
if (typeof url === 'object' && url instanceof Blob) {
url = URL.createObjectURL(url); // 创建blob地址
}
const aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName;
aLink.click();
};
txt文件
下载text文件只需要修改一下文件类型就行了
function saveTXT(csv, saveName)
{
var blob = new Blob(['\ufeff' + csv], {type: 'text/txt,charset=UTF-8'});
openDownloadDialog(blob, saveName);
}
注意事项
保存文件的文件名后缀会影响打开方式,如果是.csv
的文件名,默认打开为excel,.txt
文件结尾的默认打开方式为text文件。所以这点需要注意
参考代码
我自己在项目中的封装
downLoadTools.js
const openDownloadDialog = (url, saveName) => {
if (typeof url === 'object' && url instanceof Blob) {
url = URL.createObjectURL(url); // 创建blob地址
}
const aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName;
aLink.click();
};
export default {
/**
* 保存CSV文件
* @params csv csv文件内容
* @params saveName 保存的文件名
*/
saveCSV: (csv, saveName) => {
const blob = new Blob(['\ufeff' + csv], {type: 'text/csv,charset=UTF-8'});
openDownloadDialog(blob, `${saveName}.csv`);
},
saveTXT: (csv, saveName) => {
// const href = 'data:text/txt;charset=utf-8,\ufeff' + encodeURIComponent(csv); // ie浏览器不支持
const blob = new Blob(['\ufeff' + csv], {type: 'text/tet,charset=UTF-8'});
openDownloadDialog(blob, `${saveName}.txt`);
}
};
页面引用
import downLoadTools from '@/utils/downLoadTools'; // 引入
downLoadTools.saveTXT(csv, '文件名'); // csv是一个字符串, 最终会下载一个 文件名.txt 的文件