在使用流的方式进行下载文件时会出现常见的两种现象:
1、llegalStateException:getOutputStream() has already been called
2、ClientAbortException: java.net.SocketException
产生问题的原因正如很多高手所说一样:out.print和outputstream之间的冲突或是<%%>之外有HTML代码或空行,处理方式建议是添加下面两行就可以了:
out.clear():
out=pageContext.pushBody();
我也做了尝试,结果是由现象1变成现象2。
既然冲突就一开始就关掉out,然后处理,正常下载没有问题,取消下载时还是出现问题2
response.reset();
response.setContentType("application/x-download");
String path=request.getParameter("path");
URL url=new URL(path);
String filenamedisplay = new File(path).getName();
filenamedisplay = URLEncoder.encode(filenamedisplay, "GBK");
response.addHeader("Content-Disposition", "attachment;filename="+ filenamedisplay);
OutputStream output = null;
InputStream is = null;
try {
out.clear();
output = response.getOutputStream();
URLConnection urlConn = url.openConnection();
is = urlConn.getInputStream();
byte[] b = new byte[1024*10];
int i = 0;
while ((i = is.read(b))> 0) {
output.write(b,0, i);
}
output.flush();
output.colse();
...
...
}catch (Exception e) {
// 事实上异常都不会抛到这个地方
out.println("下载路径错误!!");
}
经过调试后发现,问题的根结是对流的处理,原本很简单的问题被复杂化!
当你点击下载,转发到该jsp页面时,此时已经建立文件流并有部分数据被缓冲。
在点击取消时,会继续执行output.write(b,0, i);一次,而这时已经断开了文件流,所以会出现现象2,处理方法就是抓住这个异常(文件流已经断开不能再进行close)
既然是单纯的下载,html相关元素都可以忽略,在正常下载(包含打开)和取消下载进行不同的处理即可
<%@page language="java" contentType="application/x-msdownload" import="java.io.*,java.net.*" pageEncoding="GBK"%><%
response.reset();
response.setContentType("application/x-download");
String path=request.getParameter("path");
URL url=new URL(path);
String filenamedisplay = new File(path).getName();
filenamedisplay = URLEncoder.encode(filenamedisplay, "GBK");
response.addHeader("Content-Disposition", "attachment;filename="+ filenamedisplay);
OutputStream output = null;
InputStream is = null;
boolean isCancelDownload = false;
try {
output = response.getOutputStream();
URLConnection urlConn = url.openConnection();
is = urlConn.getInputStream();
byte[] b = new byte[1024*10];
int i = 0;
while ((i = is.read(b))> 0) {
try{
output.write(b,0, i);
}catch(IOException e){
isCancelDownload = true;
break;
}
}
if(!isCancelDownload){
output.flush();
output.close();
output=null;
is.close();
is=null;
}else{
output=null;
is.close();
is=null;
}
} catch (Exception e) {
// 事实上异常都不会抛到这个地方
out.println("下载路径错误!!");
e.printStackTrace();
}
%>