实现文件下载的方式
-
使用
a
标签来完成(服务器文件地址下载)这是最常见的下载方式,前端实现简单,通用,但是需要把文件保存到服务器,耗费服务器资源,也有解决方式,给保存的文件设置一个过期时间,过了这个时间就审删除
<a href="./1.txt" download="1.txt">点我下载</a>
- 优点:
- 不会跳转新页面,用户体验较好
- 存储的路径是相对路径,地址一般后端返回
- 可以自定义文件名
- 缺点
- 有兼容性,download是
h5
新增属性,如果需要导出像txt,jpg
等浏览器支持直接打开的文件是不会执行下载的,而是会直接打开。 这时候可以给a标签添加一个download属性 ,所以如果不考虑兼容性的前提下,为保证文件都能正常下载而不是直接打开,都加上download
- 有兼容性,download是
- 优点:
-
二进制流导出
-
前端请求获取二进制数据流
-
后端根据前端请求,查询数据库并把查询结果转成二进制数据流。
注意:这里并不生成一个文件保存在服务器
-
后端把二进制数据流返回给前端
-
前端把二进制数据流转成
URL
对象并赋值给<a/>
标签 -
点击
<a/>
标签实现下载axios({ url: '/monitors/export', method: 'GET', responseType: 'blob',//指定返回数据格式 }).then(res => { // 将二进制数据流转成URL对象 const url = window.URL.createObjectURL( new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8', }), ); const link = document.createElement('a'); link.href = url; link.setAttribute('download', '消息数据.xls'); // 需要指定文件格式。 document.body.appendChild(link); link.click(); //点击事件 });
优点:不去要服务器生成文件,也不需要将文件保存在服务器中,可以有效较少服务器资源的占用
缺点:不通用,可能存在兼容性
-
-
window.open
var exportUrl = '接口地址' window.open(exportUrl)
优点:可以是其他
h5
标签,在标签上加点击事件即可,不存在兼容性问题缺点:用户体验可能没那么好,需要新开窗口下载文件,也不能指定文件名(好像是后端给出文件名,,,),有可能会被浏览器的安全机制拦截,,,,
-
a
标签和window.open
结合,解决兼容性和跳转页面下载var exportUrl = "/api/apps/" +$('.chose_app').attr('appid') + "/report/message/opushExport" + "?messageIds=" + $('#info-id').val().trim() + "&messageTitle=" + $('#info-title').val().trim() + "&startTime=" + searchParams.startTime + "&endTime=" + searchParams.endTime + "&messageType=" + searchParams.messageType + "&taskStatus=" + searchParams.taskStatus + "&taskIds=" + searchParams.taskIds + "&pushTimeHead=" + searchParams.pushTimeHead + "&pushTimeEnd=" + searchParams.pushTimeEnd + "&start=" + searchParams.start + "&limit=" + searchParams.limit var isSupportDownload = 'download' in document.createElement('a') if (timer !== -1) { clearTimeout(timer) } if (isSupportDownload) { timer = setTimeout(() => { timer = -1 var $a = $("<a></a>") ; $a.attr({href:exportUrl,download:'filename.text'}).hide().appendTo($("body"))[0].click(); //download属性可以设置文件名称和文件格式 },100) }else { timer = setTimeout(() => { timer = -1 window.open(exportUrl) },100) }
-
form表单提交
- form的action设置为接口地址,method设置为post,Post到后台的数据设置为input的属性 name = key,value = value的形式,如果有多个key、value的值要传递,那么就设置多个input来分别储存单个的key、value;
- 如果请求的接口可以不需要参数,那么input还是必须要一个,如果不要得话 会引起接口报错
原理:form的action相当于一个浏览器本页签/页面的一个请求,不会被后台,前台的路由拦截。所以能够提交成功。
**注意如果设置method为get,在action中的
uri
添加了参数的话,想用这个参数替代input的key、value形式来提交到后台,这参数是没有效果的,后台拿不到这些参数,真正的参数还是以input的name、value的形式储存,在submit方法执行后传递到后台。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./jquery.min.js"></script> </head> <body> <p style="font-size: 20px;color: red;">使用table标签方式将json导出xls文件</p> <button onclick='tableToExcel()'>导出</button> </body> <script> function tableToExcel() { var ary = [ { name: 'startTime', id: '1557763200000' }, { name: 'endTime', id: '1557849599999' }, { name: 'createType', id: '' }, { name: 'messageTitle', id: '' }, { name: 'taskIds', id: '' }, { name: 'messageType', id: '1,4' }, { name: 'messageIds', id: '' }, { name: 'taskStatus', id: '' }, { name: 'pushTimeHead', id: '' }, { name: 'pushTimeEnd', id: '' }, { name: 'start', id: '0' }, { name: 'limit', id: '10' } ] let idInput = ary.map(item => { return `<input type='hidden' name='idList' value=${item.id}/>`; }).join(''); let url = 'http://test.wanyol.com/api/apps/ZngnvJIM7wQusNtbqYnpH6XX/report/message/opushExport' $(`<form method='get' action='${url}'></form>`) .appendTo('body') .html(idInput) .submit() .remove(); } </script> </html>
优点:不用跳转页面,对用户友好,不存在兼容性问题
缺点:拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示
-
纯前端导出
-
将table标签,包括
tr、td
等对json
数据进行拼接,将table
输出到表格上实现,这种方法的弊端在于输出的是伪excel
,虽说生成xls
为后缀的文件,但文件形式上还是html
,代码如下<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p style="font-size: 20px;color: red;">使用table标签方式将json导出xls文件</p> <button onclick='tableToExcel()'>导出</button> </body> <script> function tableToExcel(){ //要导出的json数据 const jsonData = [ { name:'路人甲', phone:'123456', email:'123@123456.com' }, { name:'炮灰乙', phone:'123456', email:'123@123456.com' }, { name:'土匪丙', phone:'123456', email:'123@123456.com' }, { name:'流氓丁', phone:'123456', email:'123@123456.com' }, ] //列标题 let str = '<tr><td>姓名</td><td>电话</td><td>邮箱</td></tr>'; //循环遍历,每行加入tr标签,每个单元格加td标签 for(let i = 0 ; i < jsonData.length ; i++ ){ str+='<tr>'; for(let item in jsonData[i]){ //增加\t为了不让表格显示科学计数法或者其他格式 str+=`<td>${ jsonData[i][item] + '\t'}</td>`; } str+='</tr>'; } //Worksheet名 let worksheet = 'Sheet1' let uri = 'data:application/vnd.ms-excel;base64,'; //下载的表格模板数据 let template = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"> <head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet> <x:Name>${worksheet}</x:Name> <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet> </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--> </head><body><table>${str}</table></body></html>`; window.location.href = uri + base64(template) } function base64 (s) { return window.btoa(unescape(encodeURIComponent(s))) } </script> </html>
-
通过将
JSON
遍历进行字符串拼接,将字符串输出到csv
文件,代码如下 ,最终还是通过a标签下载,只是不再请求接口了,前端对文件格式进行模拟,缺点是当数据量非常庞大的时候,性能就会比较差<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <p style="font-size: 20px;color: red;">使用table标签方式将json导出xls文件</p> <button onclick='tableToExcel()'>导出</button> </body> <script> function tableToExcel(){ //要导出的json数据 const jsonData = [ { name:'路人甲', phone:'123456789', email:'000@123456.com' }, { name:'炮灰乙', phone:'123456789', email:'000@123456.com' }, { name:'土匪丙', phone:'123456789', email:'000@123456.com' }, { name:'流氓丁', phone:'123456789', email:'000@123456.com' }, ] //列标题,逗号隔开,每一个逗号就是隔开一个单元格 let str = `姓名,电话,邮箱\n`; //增加\t为了不让表格显示科学计数法或者其他格式 for(let i = 0 ; i < jsonData.length ; i++ ){ for(let item in jsonData[i]){ str+=`${jsonData[i][item] + '\t'},`; } str+='\n'; } //encodeURIComponent解决中文乱码 let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str); //通过创建a标签实现 let link = document.createElement("a"); link.href = uri; //对下载的文件命名 link.download = "json数据表.csv"; document.body.appendChild(link); link.click(); document.body.removeChild(link); } </script> </html>
-