最近做了个下载文件的功能,需要异常情况时后台直接返回浏览器弹窗,我就直接后台反回了弹窗的简单js脚本。但前端小火伴说太丑了,银行要求比较高,要美观大方,我说能实现,你讲吧。谁知,他又拉了个伙伴和UI设计,然后噼里啪啦给我讲了一大堆样式效果,听得我一肚子火。当时都周五了,再调样式,再给UI看效果,再给我们测试测,再给行方测,再加上建行的垃圾云桌面系统,卡的要死,大流程走下来,半天都不一定能完,那我周六岂不是要加班了?越想越不开心,就直接怼回去了,实现不了,就这样了!
现在刚好周末有时间,就顺便琢磨测试了一下。
之所以需要后台代码来实现弹窗效果修改,是因为前端点击完下载按钮后,此时已经不受前端发起人控制,后台将文件流读出返回浏览器,成功时调用浏览器的下载弹窗,失败时返回错误提示至浏览器。
实现浏览器弹窗效果的修改,需要js中重写alrt方法,对于后台开发来说,也只是把前端的css、js代码搬到后台,返回页面上。其实,实现起来不难,但是把前端代码复制到java中,涉及到单双引号转换、转义,很容易在细节上出错,我就是在细节上出错,导致调了一下午才调好样式。
下面介绍一下我琢磨测试的过程和效果:
分三种情况:
第一:简单型的,没有样式要求,浏览器自带的弹窗效果就可以满足的,直接alert即可。
第二:样式写在css或js中,然后直接放到java字符串中。
第三种:抽取了css、js到外文件夹下,此时需要引入css、js到java字符串中。
1、导出文件代码:
@RequestMapping("/exportExcel")
public void exportFile(HttpServletRequest request, HttpServletResponse response){
String filename = request.getParameter("fileName");
DataInputStream in = null;
OutputStream out = null;
try{
response.reset();// 清空输出流
String resultFileName = "导出文件名" + System.currentTimeMillis() + ".xls";
resultFileName = URLEncoder.encode(resultFileName,"UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment; filename=" + resultFileName);// 设定输出文件头
// response.setContentType("application/msexcel");// 定义输出类型
//输入流:本地文件路径
// String contexPath= request.getSession().getServletContext().getRealPath("/") ;
String contexPath ="D:\\A_WorkSpace\\decorate-furniture\\decorate_web\\src\\main\\resources\\1报名名单.xls";
// String contexPath ="D:\\A_WorkSpace\\decorate-furniture\\decorate_web\\src\\main\\resources\\a配置说明.doc";
in = new DataInputStream(new FileInputStream(new File(contexPath )));
//输出流a
out = response.getOutputStream();
//输出文件
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
} catch(Exception e){
e.printStackTrace();
response.reset();
try {
OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
String data = "<script language='javascript'>alert(\"\\u64cd\\u4f5c\\u5f02\\u5e38\\uff01\"); </script>";
writer.write(data);
writer.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}finally {
if(null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2、仅仅实现alert弹窗效果,不做样式的修改,代码中红色粗体部分:
(1)代码所示:
String data = "<script language='javascript'>alert(\"\\u64cd\\u4f5c\\u5f02\\u5e38\\uff01\"); </script>";
(2)弹窗效果图:
3、css、js未抽取时,代码中红色粗体部分::
(1)代码:
String data = "<style type='text/css'>\n" +
" *{margin:0;padding:0;font-size:12px;}\n" +
" .ul{list-style:none;margin:0px;padding:0px;width:100%}\n" +
" .title{background:#F2F2F2;text-align:left;padding-left:20px;line-height:60px;border:1px solid #999;}\n" +
" .content{background:#D1E0F1;text-align:center;height:95px;line-height:95px;border-left:1px solid #999;border-right:1px solid #999;color:#F0F;}\n" +
" .btn-wrap{background:#F2F2F2;text-align:center;height:60px;line-height:25px; border:1px solid #999;}\n" +
" .btn{width:80px;height:40px;background:#999;margin-top:10px;border:1px solid #FFF;cursor:pointer;color:#333;}\n" +
" .btn:hover{color:#666;}\n" +
"</style>"+
"<script>"+
"window.alert = function(str){\n" +
" var shield = document.createElement('DIV');\n" +
" document.body = document.createElement('BODY');\n" +
" document.body = document.createElement(\"BODY\");\n" +
" shield.id = 'shield';\n" +
" shield.style.position = 'absolute';\n" +
" shield.style.left = '50%';\n" +
" shield.style.top = '50%';\n" +
" shield.style.width = '300px';\n" +
" shield.style.height = '300px';\n" +
" shield.style.marginLeft = '-150px';\n" +
" shield.style.marginTop = '-150px';\n" +
" shield.style.zIndex = '25';\n" +
" var alertFram = document.createElement('DIV');\n" +
" alertFram.id='alertFram';\n" +
" alertFram.style.position = 'absolute';\n" +
" alertFram.style.width = '300px';\n" +
" alertFram.style.height = '200px';\n" +
" alertFram.style.left = '50%';\n" +
" alertFram.style.top = '0';\n" +
" alertFram.style.marginLeft = '-140px';\n" +
" alertFram.style.marginTop = '120px';\n" +
" alertFram.style.textAlign = 'center';\n" +
" alertFram.style.lineHeight = '150px';\n" +
" alertFram.style.zIndex = '300';\n" +
" strHtml = '<ul class=\"ul\"><li class=\"title\"><img src=\"http://127.0.0.1:8081/timg.jpg\" style=\"width: 40px;height: 40px\"></li><li class=\"content\">'+str+'</li><li class=\"btn-wrap\"><input type=\"button\" value=\"\\u786e\\u5b9a\" onclick=\"doOk()\" class=\"btn\"/></li></ul>';\n" +
" alertFram.innerHTML = strHtml;\n" +
" document.body.appendChild(alertFram);\n" +
" document.body.appendChild(shield);\n" +
" this.doOk = function(){ alertFram.style.display = 'none'; shield.style.display = 'none'; }\n" +
" alertFram.focus();\n" +
" document.body.onselectstart = function(){return false;};\n" +
" }\n" +
" alert('\\u64cd\\u4f5c\\u5f02\\u5e38\\uff01');"
+"</script>";
(2)效果
4、css、js抽取出来通过路径引入方式实现,代码中红色粗体部分:
(1)data值为:
String data ="<head><link href='http://127.0.0.1:8081/style.css' rel='stylesheet' type='text/css'></head>"+
"<script>\n"+
"window.alert = function(str){\n" +
" var shield = document.createElement('DIV');\n" +
" document.body = document.createElement('BODY');\n" +
" document.body = document.createElement(\"BODY\");\n" +
" shield.id = 'shield';\n" +
" shield.style.position = 'absolute';\n" +
" shield.style.left = '50%';\n" +
" shield.style.top = '50%';\n" +
" shield.style.width = '300px';\n" +
" shield.style.height = '300px';\n" +
" shield.style.marginLeft = '-150px';\n" +
" shield.style.marginTop = '-150px';\n" +
" shield.style.zIndex = '25';\n" +
" var alertFram = document.createElement('DIV');\n" +
" alertFram.id='alertFram';\n" +
" alertFram.style.position = 'absolute';\n" +
" alertFram.style.width = '300px';\n" +
" alertFram.style.height = '200px';\n" +
" alertFram.style.left = '50%';\n" +
" alertFram.style.top = '0';\n" +
" alertFram.style.marginLeft = '-140px';\n" +
" alertFram.style.marginTop = '120px';\n" +
" alertFram.style.textAlign = 'center';\n" +
" alertFram.style.lineHeight = '150px';\n" +
" alertFram.style.zIndex = '300';\n" +
" strHtml = '<ul class=\"ul\"><li class=\"title\"><img src=\"http://127.0.0.1:8081/yellow.png\" style=\"width: 40px;height: 40px\"></li><li class=\"content\">'+str+'</li><li class=\"btn-wrap\"><input type=\"button\" value=\"\\u786e\\u5b9a\" onclick=\"doOk()\" class=\"btn\"/></li></ul>';\n" +
" alertFram.innerHTML = strHtml;\n" +
" document.body.appendChild(alertFram);\n" +
" document.body.appendChild(shield);\n" +
" this.doOk = function(){ alertFram.style.display = 'none'; shield.style.display = 'none'; }\n" +
" alertFram.focus();\n" +
" document.body.onselectstart = function(){return false;};\n" +
" }\n" +
" alert('\\u64cd\\u4f5c\\u5f02\\u5e38\\uff01');"
+"</script>";
(2)展示效果为:
在java的字符串中写css、js、html代码时,一定要细心,因为没有提醒,也很容易出错。
同样,该方式也适用于后台重写prompt、confirm样式。