本文总结,javaweb下载文件遇到的各种问题
1.html5支持的文件下载
非常简单代码如下:
<a download="下载文件.txt">下载文件</a>
这种方式不支持ie浏览器
2.需要后台支持的文件下载:
前端代码如下:
function getRootPath() {
//获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
var curWwwPath = window.document.location.href;
//获取主机地址之后的目录,如: uimcardprj/share/meun.jsp
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
//获取主机地址,如: http://localhost:8083
var localhostPaht = curWwwPath.substring(0, pos);
//获取带"/"的项目名,如:/uimcardprj
var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
return (localhostPaht + projectName);
}
function downloadExcel(fileName) {
fileName = encodeURI(fileName);
var url = getRootPath() + "/static/excel/" + fileName;
window.location.href = "data/downloadexcel?fileName=" + fileName + "&url=" + url;
}
此处需要传递下载文件的文件名称与文件的地址(为了避免服务器路径问题,此处直接使用前端传递的url路径地址,这种方式也可以用来下载第三方网站上的文件资源),注意对于文件名称需要处理文件名称中的中文字符与特殊字符需要使用js方法encodeURI对文件名称编码
后台代码:
/**
* 下载文件
*
* @param fileName
* @param url
* @return
*/
@RequestMapping(value = "/index/download", method = RequestMethod.GET)
@ResponseBody
public void download(String fileName, String url) {
logger.info("下载文件:" + url);
// 需要对url进行编码,默认情况下,只编码最后一个 / 之后的内容
int index = url.lastIndexOf("/") + 1;
this.response.reset();
this.response.setContentType("multipart/form-data");
HttpURLConnection conn = null;
InputStream inputStream = null;
try {
url = url.substring(0, index) + URLEncoder.encode(url.substring(index), "utf-8");
//注意URLEncoder.encode会将空格转换为+,需要做特殊处理
url = url.trim().replaceAll("\\+", "%20");
this.response.setHeader("Content-Disposition",
"attachment;fileName=" + processFileName(this.request, fileName));
URL url1 = new URL(url);
conn = (HttpURLConnection) url1.openConnection();
inputStream = conn.getInputStream();
ServletOutputStream out = this.response.getOutputStream();
IOUtils.copy(inputStream, out);
out.flush();
} catch (IOException e) {
logger.error("下载模板文件出错", e);
} finally {
if (null != inputStream) {
try {
inputStream.close();
} catch (IOException e) {
logger.error("下载模板文件出错", e);
}
}
if (null != conn) {
try {
conn.disconnect();
} catch (Exception e) {
logger.error("下载模板文件出错", e);
}
}
}
}
/**
* @Title: processFileName
* @Description: ie, chrom, firfox下处理文件名显示乱码
*/
public static String processFileName(HttpServletRequest request,
String fileNames) {
String codedfilename = null;
try {
String agent = request.getHeader("USER-AGENT");
if (null != agent && agent.indexOf("MSIE") > -1 || null != agent
&& agent.indexOf("Trident") > -1) {// ie
String name = java.net.URLEncoder.encode(fileNames, "UTF8").replaceAll("\\+","%20");
codedfilename = name;
} else {// 火狐,chrome等
codedfilename = new String(fileNames.getBytes("UTF-8"),
"iso-8859-1");
}
} catch (Exception e) {
logger.error("文件名称编码出错", e);
}
return codedfilename;
}
下载文件代码需要注意的地方就只有文件名称的编码问题,其他代码很简单,需要特别注意URLEncoder.encode将空格转换为+,需要特殊处理转换为%20
3.下载后台实时生成的文件
简单的后台实时生成文件基本代码和步骤二一致,只是将从网络获取的文件改为从本机获取就行了
4.使用post方法下载文件
post方法下载文件主要可以通过两种方式解决
第一种将post提交到当前页面的隐藏iframe即可,但这种方式在ie和chmore中会有两种表现形式(一种直接在当前页面下载,一种会打开一个空白页下载)
var downLoadFile = function (options) {
var config = $.extend(true, {method: 'post'}, options);
var $iframe = $('<iframe id="down-file-iframe" />');
var $form = $('<form target="down-file-iframe" method="' + config.method + '" />');
$form.attr('action', config.url);
for (var key in config.data) {
var input = $("<input hidden>");
input.attr("name", key);
input.val(config.data[key]);
$form.append(input);
}
$iframe.append($form);
$(document.body).append($iframe);
$form[0].submit();
$iframe.remove();
}
//调用方法
downLoadFile({
url: '...', //请求的url
data: {
name:"",
size:"",
......
}//要发送的数据
});
使用以上方式即可使用post的方法下载文件
第二种方法很简单,可以先用post方式上传参数,将参数以缓存的形式存储在服务端并返回key给前端,再在post的回调方法中使用get方式传递key给后台下载文件
样例代码很简单,如下:
$.post("download",params, function (data) {
if (data.success) {
window.location.href = "download?generatorId=" + data.data;
} else {
alert(data.msg);
}
})