我试图了解这是如何发生以及如何解决的。 我有一个带有jsp页面的jsf请求bean,如下所示:(汇总)
<f:view locale="#{drcBean.userLocale}">
</f:view>
支持bean代码:
public Locale getUserLocale() {
return new Locale("en");
}
最后,当会话启动时,会调用此方法(将文件发送到客户端)
private void sendFile()
{
byte[] config = ...;
String clientFileName = "iphone.mobileconfig";
// Prepare.
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
// File file = new File(getFilePath(), getFileName());
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open file.
ByteArrayInputStream bais = new ByteArrayInputStream(config);
input = new BufferedInputStream(bais);
// Init servlet response.
response.reset();
response.setContentType("application/x-apple-aspen-config");
response.setHeader("Content-Disposition", "attachment; filename=\"" + clientFileName
+ "\"");
response.setContentLength((int) config.length);
// if (logger.isTraceEnabled()) {
// logger.trace("Writing XML Script:" + new String(scriptDataByteArray));
// }
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Finalize task.
output.flush();
} catch
我收到IllegalStateException
个异常,呼叫response.getOutputStream()
我没有得到的是,如果未定义locale="#{drcBean.userLocale}"
,则不会发生这种情况。 (意思是,我省略了视图的locale
标签,问题就消失了)
还有一个证据表明,我最终收到的文件是提到的JSP页面,在我看来,这意味着以某种方式发送了新页面并中止了文件发送。但是这与locale
有什么关系呢?
此外,如果我使用<f:view locale="en">
而不是使用支持bean作为值,它可以正常工作。
答案 0 :(得分:0)
如果您尝试将文件下载给用户,为什么还要对区域设置感到困扰?
无论如何,我不知道你为什么会得到IllegalArgumentException。当您尝试使用已经写入的OutputStream时,通常会发生这种情况。
如果我使用以下jsp:
<%@ page import="uk.co.farwell.MyBean" %>
<f:view locale="en">
<%
MyBean bean = (DossierBean) pageContext.findAttribute ("bean");
bean.sendFile(response);
%>
</f:view>
在bean中使用以下代码:
public void sendFile(HttpServletResponse response) throws Exception {
byte[] config = "foobar".getBytes();
String clientFileName = "iphone.mobileconfig";
BufferedInputStream input = null;
BufferedOutputStream output = null;
ByteArrayInputStream bais = new ByteArrayInputStream(config);
input = new BufferedInputStream(bais);
response.reset();
response.setContentType("application/x-apple-aspen-config");
response.setHeader("Content-Disposition", "attachment; filename=\"" + clientFileName + "\"");
response.setContentLength((int) config.length);
output = new BufferedOutputStream(response.getOutputStream(), 1024);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
}
我得到一个IllegalArgumentException。如果这是你得到的错误,那么直接尝试使用Servlet。
public final class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
byte[] config = "foobar".getBytes();
resp.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
resp.setContentType("application/rtf");
resp.setContentLength(config.length());
resp.getOutputStream().write(config.getBytes());
resp.getOutputStream().flush();
resp.getOutputStream().close();
}
}
或类似的。这比使用jsp下载文件更可靠。
答案 1 :(得分:0)
此问题的真正解决方案是在加载JSP页面之前发送文件。 为此,我注册了一个phaselistener并在JSP页面之前发送了该文件。
public class DrcPhaseListener implements PhaseListener {
@Override
public void afterPhase(PhaseEvent pe) {
..... send file here ....
}
问题是,我怀疑,JSP页面已经开始向响应发送日期,当我尝试从bean发送文件时为时已晚。 上面的修复将强制文件在页面尚未开始加载的阶段发送,因此没有任何内容写入响应。
答案 2 :(得分:0)
您需要在操作方法的末尾调用FacesContext#responseComplete()
以防止JSF导航到某个页面(默认为提交表单的页面)。
public void download() {
sendFile();
FacesContext.getCurrentInstance().responseComplete();
}