我已经为此工作了几个小时:
当按下按钮时,我需要生成 XML 并将其下载给用户。我已经尝试将 primefaces StreamedContent 与 p:fileDownload 一起使用 - 但我得到的唯一输出是实际页面的 .xhtml 源。我可以在返回 StreamedContent 之前使用日志语句来显示它的内容,并且我可以在那里正确地看到我的 XML 代码,但是下载的文件总是有页面源代码。(我也尝试了很多其他方法,下载 jpg 文件,更改 bean 以直接生成响应并通过 h:commandButton 中的操作调用方法 - 始终获取页面源!)。
这是我的 .xhtml :
<p:commandButton value="Create XML Bid/Offer"
id="createXMLButton"
disabled="#{portfolioBean.noPortfolioSelected}"
ajax="false"
icon="ui-icon-arrowthichk-s">
<p:fileDownload value="#{portfolioBean.order}" />
</p:commandButton>
(备用)
<h:commandButton value="Create XML Bid/Offer"
id="createXMLButton"
disabled="#{portfolioBean.noPortfolioSelected}"
ajax="false"
icon="ui-icon-arrowthichk-s"
action="#{portfolioBean.download()}" />
和支持 bean 方法:
public StreamedContent getOrder() {
...
}
(备用)
public String download() {
...
}
我没有包含方法体,因为我知道它们返回正确的 XML……这似乎真的是 JSF 魔法中的东西。这是配置问题还是什么?
谢谢!
更新 好的 - 我已经从我的代码中删除了所有内容,所以就是这样:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Edison Energy Portal</title>
</h:head>
<h:body>
<h:form id="form">
<h:commandButton value="Download PDF" action="#{downloadJPG.downloadFile}" />
</h:form>
</h:body>
</html>
public class DownloadJPG {
// Constants ----------------------------------------------------------------------------------
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
// Actions ------------------------------------------------------------------------------------
public void downloadFile() throws IOException {
// Prepare.
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
File file = new File("....", "....");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open file.
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
// Init servlet response.
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"...\"");
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();
} finally {
// Gently close streams.
close(output);
close(input);
}
// Inform JSF that it doesn't need to handle response.
// This is very important, otherwise you will get the following exception in the logs:
// java.lang.IllegalStateException: Cannot forward after response has been committed.
facesContext.responseComplete();
}
// Helpers (can be refactored to public utility class) ----------------------------------------
private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail it. It may be useful to
// know that this will generally only be thrown when the client aborted the download.
e.printStackTrace();
}
}
}
}
我检查了我的源图像文件,它没有损坏。BalusC 的代码尝试了一次,然后我用 XML 文件替换了当前的 jpg,更改了 MIME 类型,此后没有任何效果。好像有什么不好的东西在tomcat中绊倒了,我无法将其取出或重置(我尝试通过eclipse手动清理tomcat,甚至重新启动我的盒子)。
这是一个真正的装腔作势者。
更新:我已经开始 eclipse clean - 没有运气。我真的没主意了。我不得不认为这是某处的配置,因为我知道这段代码可以工作(我已经看过了)。