求解!!!JSF实现下载功能老是报这个错,getOutputStream() has already been called for this response。 10

这个问题都折磨了我好几天了,我刚刚接触jsf差不多一个多月我实在是不会解,网上找的例子还是报一样的错,我实在是无语极了。。。哪位高人帮我解决一下吧这是我的下载代码:try... 这个问题都折磨了我好几天了,我刚刚接触jsf差不多一个多月 我实在是不会解,网上找的例子还是报一样的错 ,我实在是无语极了。。。 哪位高人帮我解决一下吧
这是我的下载代码:
try{
File exportFile = new File(excelName); //生成的Excle文件的绝对路劲
HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
httpServletResponse.setHeader("Content-disposition",
"attachment; filename=" + strfileName);
httpServletResponse.setContentLength((int) exportFile.length());
httpServletResponse.setContentType("application/x-download");
// httpServletResponse.setContentType("application/vnd.ms-excel");
byte[] b = new byte[1024];
int i = 0;
FileInputStream fis = new java.io.FileInputStream(exportFile);
while ((i = fis.read(b)) > 0) {
servletOutputStream.write(b, 0, i);
}
} catch (IOException e) {
e.printStackTrace();
}
FacesContext.getCurrentInstance().responseComplete();

这个是报错信息:

警告: PWC3991: getOutputStream() has already been called for this response
java.lang.IllegalStateException: PWC3991: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:705)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:225)
at com.sun.faces.context.ExternalContextImpl.getResponseOutputWriter(ExternalContextImpl.java:723)
at com.sun.faces.context.PartialViewContextImpl.createPartialResponseWriter(PartialViewContextImpl.java:431)
at com.sun.faces.context.PartialViewContextImpl.access$300(PartialViewContextImpl.java:71)

请各位大哥大姐尽快帮我解决解决吧 ~~~小妹我无限的感激啊。。。。。
展开
 我来答
东方猫
2012-07-12 · TA获得超过303个赞
知道小有建树答主
回答量:290
采纳率:0%
帮助的人:287万
展开全部
问题:你需要清空并且关闭流对象。
我提供两种解决方案,并且解决了中文文件名乱码问题,兼容IE和火狐两种浏览器。
你可以选择。
方案一:代码写在一个.jsp文件中。

下载请求页面传递过来的参数(当然具体看你要几个参数)
<rich:column>
<h:outputLink value="file.jsp" rendered="true">
<f:param name="docId" value="#{item.id.docId}" / >
<f:param name="revNo" value="#{item.id.revNo}" />
<f:param name="attachmentNo" value="#{item.id.attachmentNo}" />
<f:param name="filename" value="#{item.fileName}" />
<f:param name="storageName" value="#{item.storageName}" />
<h:outputText value="#{item.fileName}" />
</h:outputLink>
</rich:column>
file.jsp 文件代码:
<%@page language="java" contentType="application/octet-stream"pageEncoding="utf-8"%>
<%@page import="java.io.*,java.util.*,java.net.URLEncoder"%>
<%response.reset();
String ATTACHMENTSTOREPATH = 已经上传了的附件的路径,自己应该知道?
int docId = 0;
int revNo = -1;
int attachmentNo = 0;
String filename = null;
String storageName = null;

try {
docId = Integer.parseInt(request.getParameter("docId"));
revNo = Integer.parseInt(request.getParameter("revNo"));
attachmentNo = Integer.parseInt(request.getParameter("attachmentNo"));
//在火狐浏览器下载,含空格的文件名会出现异常,于是将空格用下划线代替
filename = (new String(request.getParameter("filename").
getBytes("ISO-8859-1"),"UTF-8")).replace(" ", "_");

//将空格转化为下划线后重新对文件名进行UTF-8编码
filename = java.net.URLEncoder.encode(filename, "UTF-8"); storageName = request.getParameter("storageName");
} catch (NumberFormatException nfe) {

}
if (docId >= 0 && revNo > -1 && attachmentNo >= 0) {
String filePath = null;
filePath = ATTACHMENTSTOREPATH + File.separator + storageName;
response.setContentType("application/octet-stream");
//因为浏览器会将字符GBK编码,所以从数据库获得的UTF-8需要转换成GBK
//UTF-8一个汉字24位,GBK一个汉字16位
//Start UTF-8 to GBK(相对以前的程序主要就是修改了这里)
String str=filename;
StringBuffer sb = new StringBuffer();
for(int i=0; i<str.length(); i++) {
char c = str.charAt(i);
switch (c) {
case '+':
sb.append(' ');
break;
case '%':
try {
sb.append((char)Integer.parseInt(
str.substring(i+1,i+3),16));
}
catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
i += 2;
break;
default:
sb.append(c);
break;
}
}
String result = sb.toString();
result= new String(result.getBytes("ISO-8859-1"),"UTF-8");
response.addHeader("Content-Disposition", "attachment; filename=" + new String(result.getBytes("GBK"),"ISO-8859-1"));
//End UTF-8 to GBK
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
bos = new BufferedOutputStream(response.getOutputStream());
bis = new BufferedInputStream(new FileInputStream(filePath));
byte[] buffer = new byte[1024];
int n = -1;
while ((n = bis.read(buffer)) > -1) {
bos.write(buffer, 0, n);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null)
bis.close();
if (bos != null){
out.clear(); out = pageContext.pushBody(); bos.close(); } bis = null;
bos = null;
}
}
%>
此方案中如果你去掉:out.clear();
out = pageContext.pushBody();
报的错将和你的一模一样,不信你试试?

方案二:用Servlet下载,和你的是一样的。
还是页面过来的参数: <h:outputLink value="/***/***">其中/***/***是你调用的Servlet
<rich:column>
<h:outputLink value="/***/***">
<f:param name="storage" value="#{list.storageName}" />
<f:param name="display" value="#{list.displayName}" />
<f:param name="status" value="#{list.status}" />
<h:outputText styleClass="input1_9pt_ul" value="#{list.displayName}" />
</h:outputLink>
</rich:column>

public class PrFileServlet extends HttpServlet {
//stauts判断使用哪个路径
private String UPLOAD_TEMP_PATH = "临时路径(还没有保存)";
private String UPLOAD_PATH = "文件路径(已经保存了文件)";

protected void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
String storageName =
(request.getParameter("storage")==null?"":request.getParameter("storage"));
//在火狐浏览器下载,含空格的文件名会出现异常,于是将空格用下划线代替
String displayName =new String(request.getParameter("display").getBytes("ISO-8859-1"),"UTF8").replace(" ", "_");
//将空格转化为下划线后重新对文件名进行UTF-8编码
displayName = java.net.URLEncoder.encode(displayName, "UTF-8");
String status = (request.getParameter("status")==null?"":request.getParameter("status"));
String code = (request.getParameter("code")==null?"":request.getParameter("code"));
String filePath = "";
if (status.equals("N")) {
filePath = UPLOAD_PATH + "//" + storageName.substring(0, 6);
} else if (status.equals("T")) {
filePath = UPLOAD_TEMP_PATH;
}
File file = new File(filePath, storageName);
if (file == null) {
response.sendRedirect("/weberp/workflow/pr/fileNotFound.jsp");
return;
}
if (!file.exists()) {
response.sendRedirect("/weberp/workflow/pr/fileNotFound.jsp");
return;
}
String contentType = getServletContext().getMimeType(storageName);
if (contentType == null) {
contentType = "application/octet-stream";
}
BufferedInputStream input = null;
BufferedOutputStream output = null;

try {
input = new BufferedInputStream(new FileInputStream(file));
int contentLength = input.available();

// Init servlet response.
response.reset();
response.setContentType(contentType);
response.setContentLength(contentLength);
//因为浏览器会将字符GBK编码,所以从数据库获得的UTF-8需要转换成GBK
//UTF-8一个汉字24位,GBK一个汉字16位
//Start UTF-8 to GBK(相对以前的程序主要就是修改了这里)
String str=displayName;
StringBuffer sb = new StringBuffer();
for(int i=0; i<str.length(); i++) {
char c = str.charAt(i);
switch (c) {
case '+':
sb.append(' ');
break;
case '%':
try {
sb.append((char)Integer.parseInt(
str.substring(i+1,i+3),16));
}
catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
i += 2;
break;
default:
sb.append(c);
break;
}
}
String result = sb.toString();
result= new String(result.getBytes("ISO-8859-1"),"UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + new String(result.getBytes("GBK"),"ISO-8859-1"));
//End UTF-8 to GBK
output = new BufferedOutputStream(response.getOutputStream());

// Write file contents to response.
for (int data; (data = input.read()) != -1;) {
output.write(data);
}

// Finalize task.
output.flush();
} catch (IOException e) {
// Something went wrong?
e.printStackTrace();
} finally {
// Gently close streams.
close(output);
close(input);
}
}

private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
好好看懂,要有耐心。希望对你有所帮助。
张存祥
2012-11-05 · TA获得超过159个赞
知道答主
回答量:23
采纳率:0%
帮助的人:22.1万
展开全部
你这个问题解决了吗?是哪里有错误啊?真的是要加上那两局吗?
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式