实现文件下载的方式

实现文件下载的方式

  • 使用a标签来完成(服务器文件地址下载)

    这是最常见的下载方式,前端实现简单,通用,但是需要把文件保存到服务器,耗费服务器资源,也有解决方式,给保存的文件设置一个过期时间,过了这个时间就审删除

    <a href="./1.txt" download="1.txt">点我下载</a>
    
    • 优点:
      1. 不会跳转新页面,用户体验较好
      2. 存储的路径是相对路径,地址一般后端返回
      3. 可以自定义文件名
    • 缺点
      1. 有兼容性,download是h5新增属性,如果需要导出像txt,jpg等浏览器支持直接打开的文件是不会执行下载的,而是会直接打开。  这时候可以给a标签添加一个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表单提交

    1. form的action设置为接口地址,method设置为post,Post到后台的数据设置为input的属性 name = key,value = value的形式,如果有多个key、value的值要传递,那么就设置多个input来分别储存单个的key、value;
    2. 如果请求的接口可以不需要参数,那么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>
      
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值