新人要做一个下载功能,为了良好的用户体验,要求点击下载之后弹出一个正在下载的提示框。
既然要有提示框,那下载完成之后肯定是要关闭提示框的,所以一开始我是用ajax来实现的,后面发现ajax根本不能获取到response的内容,所以无法完成下载。
之后我用from表单来提交,这个方法可是可以下载文件,但问题是不能获取到文件的下载状态,不能判断它是否完成下载然后好关闭提示框。
然后我又找了种方法,就是用XMLHttpRequest。代码如下:
前端页面代码:
下载
js代码
function downloadFile() {
loading('正在下载...');
//这是我自定义的提示框
var url = "/sys/downloadFile";
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
var headerName = xhr.getResponseHeader("Content-disposition");
var fileName = decodeURIComponent(headerName).substring(20);
var a = document.createElement('a');
a.download = fileName;
a.href = https://www.it610.com/article/e.target.result;
$("body").append(a);
// 修复firefox中无法触发click
a.click();
closeLoading();
//关闭提示框
$(a).remove();
}
}
};
xhr.send();
}
后台代码:
response.setContentType("application/vnd.ms-excel;
charset=utf-8");
response.setCharacterEncoding("UTF-8");
//XMLHttpRequest的跨域问题,设置为*号则表示允许任何域名跨域访问
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST");
response.setHeader("Content-Disposition", "attachment;
filename="+filename,"UTF-8"));
OutputStream out = response.getOutputStream();
//省略其他代码
写完这些后,确实可以下载了,没问题,然后我把代码提交到svn上去后,测试告诉我,有问题,点击下载的时候,浏览器控制台输出500错误,但是我在我自己的电脑上运行确实没问题,我又叫一个其他同事更新项目,运行下载也没有问题,我不知道为什么在服务器上运行就不行,我在网上找了一下午也没找到我这种情况的问题,没办法我只能不用这种方法了。然后找来找去,只能又用form提交下载。
最后,我终于找到一种用form提交可以获取文件的下载状态的办法。我参考的是这篇文章:https://blog.csdn.net/weixin_38661747/article/details/80754258
代码如下:
js代码:
function downloadFile() {
try{
var downloadToken = +new Date();
//设置一个时间戳发送到后台
var url = "/sys/downloadFile?downloadToken="+downloadToken;
loading('正在下载...');
//这个提示框是我自定义的提示框
var form = $("");
form.attr("action", url);
form.attr("method", "post");
form.attr("enctype", "multipart/form-data");
$("body").append(form);
form.submit();
form.remove();
function checkToken() {
//前端实时监测时间戳和后台设置的cookie值是否相等,相等就说明文件下载成功,就可以关闭提示框
var token = getCookie("downloadToken");
if (token && token == downloadToken) {
clearTimeout(downloadTimer);
closeLoading();
//关闭提示框
}
}
var downloadTimer = setInterval(checkToken, 1000);
}catch(e){
alert(e.name + ": " + e.message);
}
}
//获取后台设置的cookie值
function getCookie(cookieName) {
var strCookie = document.cookie;
var arrCookie = strCookie.split(";
");
for(var i = 0;
i < arrCookie.length;
i++){
var arr = arrCookie[i].split("=");
if(cookieName == arr[0]){
return arr[1];
}
}
return "";
}
后台代码:
//将时间戳设置到cookie中
Cookie cookie = new Cookie("downloadToken", downloadToken);
cookie.setPath("/");
cookie.setMaxAge(-1);
response.addCookie(cookie);
response.setContentType("application/vnd.ms-excel;
charset=utf-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment;
filename="+filename,"UTF-8"));
OutputStream out = response.getOutputStream();
//省略其他代码
【java|form表单提交下载文件获取文件的是否下载完成】写完之后测试,可以没问题,然后提交,最后并没有再出现问题(松了一口气)
就一个下载弄了我花了我两天时间,当然单单是下载的话肯定很简单,主要是要监听文件的下载状态,好加个提示框和关闭提示框,不然我也不用改这么多次代码了。
还有一个问题就是XMLHttpRequest下载为什么本地下载没问题但是上传到公司的服务器运行就不行,知道的话可以告诉我哟~
推荐阅读
- java|java 聊天室 私聊_Java WebSocket实现网络聊天室(群聊+私聊)
- 还用 != null 判空(新姿势,值得学习!)
- java|货拉拉 Android H5离线包原理与实践
- Spring|Spring Boot Admin 介绍及使用
- Java|Spring Boot Start之mqtt框架封装
- spring|spring boot 返回图片流
- idea|spring boot 集成redis
- spring|Spring Boot的特点
- postman|postman工具的使用