spring mvc 使用ajax实现文件下载 (XMLHttpRequest Level2应用)

如何获取后台文件流,并弹出下载框?

前台:

1.模拟a标签的点击

function exportExcel(){
        var a = document.createElement("a");
        a.href = '/lowFareFind/exportExcel?token='+token;
        a.target = '_blank'; //新的标签页
        a.click(); //模拟点击并触发a标签默认行为     (使用jquery 方式click() 只会触发绑定的click函数行为,不会触发元素默认行为) ,如何触发默认行为?
    }

 

2.通过隐藏iframe

<iframe id="iframeFile" style="display:none"></iframe>
function exportExcel(){
        document.getElementById('iframeFile').src = '/lowFareFind/exportExcel?token='+token;
    }

注意 :需要设置X-Frame-Options HTTP响应头 值为 SAMEORIGIN , 默认为DENY (会拒绝引入资源到iframe中)

(Refused to display 'your url...' in a frame because it set 'X-Frame-Options' to 'DENY'.)

3.XMLHttpRequest Level 2 + iframe

XMLHttpRequest 2 支持了对流的获取操作,得到blob对象,使用URL.createObjectURL 获得对象URL

<iframe id="iframeFile" style="display:none"></iframe>
function exportExcel(){
        var oReq = new XMLHttpRequest();
        var url = '/lowFareFind/exportExcel?token='+token;
        oReq.open('get',url,true);
        oReq.responseType = 'blob';
        oReq.onload = function(e){
            if(oReq.status == 200)
                var blob = oReq.response;
                document.getElementById('iframeFile').src = window.URL.createObjectURL(blob); 
                console.log(blob);
        };
        oReq.send();
        
    }

4.XMLHttpRequest Level 2 + html5 

XMLHttpRequest 2 支持了对流的获取操作,返回的blob对象,通过URL.createObjectURL生成临时url

html5的a标签支持download属性,表明为一个下载链接

function exportExcel(){
        var oReq = new XMLHttpRequest();
        var url = '/lowFareFind/exportExcel?token='+token;
        oReq.open('get',url,true);
        oReq.responseType = 'blob';
        oReq.onload = function(e){
            if(oReq.status == 200)
                var blob = oReq.response;
                var url = window.URL.createObjectURL(blob); 
                var a = document.createElement('a');
                a.href = url;
                a.target="_blank";
                a.download = "合并后.pdf";//html5新属性 表示这是一个下载链接而不是普通链接,同时可以指定文件名字
                //a.click(); //触发a元素,jquery对象的click()无法触发a标签原生行为 firebox不兼容
                var evt = document.createEvent("MouseEvents");
                evt.initEvent("click", true, true);
                a.dispatchEvent(evt);   
        };
        oReq.send();
        
    }

 

 

后台

从redis中提取数据对象list,包装数据为Workbook对象并返回文件流

@RequestMapping("/exportExcel")
    public void exportExcel(@RequestParam("token") String token,HttpServletResponse response){
        try {
            //redis中读取list数据
            String jsonStr = (String) redisTemplate.opsForHash().get(token, "ticketList");
            //将json字符串转java对象
            List<LowFareFindTicketVO> list = JSON.parseArray(jsonStr, LowFareFindTicketVO.class);
            //把List集合写入excel表
            Workbook workbook = lowFareFindExcelService.writeExcelFile(list);
            String fileName = IdGenerator.getTimestamp()+ "_比较后结果.xlsx";
            //文件名转码
            fileName = URLEncoder.encode(fileName,"utf-8");
            response.setHeader("Content-disposition","attachment; filename=" + fileName);
            response.setHeader("X-Frame-Options", "SAMEORIGIN");
            response.setContentType("application/msexcel");
            ServletOutputStream servletOut = response.getOutputStream();
            //excel输出
            workbook.write(servletOut);
        } catch (Exception e){
            logger.error("#",e);
        }
    }

 

HTTP头 - response响应头属性设置

 

ContentType : 设置MIME类型,指定返回文件类型   MIME类型解释

X-Frame-Options : 给浏览器指示允许一个页面可否在 <frame><iframe>或者 <object> 中展现的标记 ,网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。 X-Frame-Options

Content-disposition : 消息头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。 Content-Dispostion

参考 MDN WEB DOCS

        XMLHttpRequest Level 2

        

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值