如何获取后台文件流,并弹出下载框?
前台:
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