JSF2下载文件返回xhtml页面源代码 [英] JSF2 download file returns xhtml page source
问题描述
我已经为此工作了几个小时:
I've been working on this for hours :
按下按钮时,我需要生成XML并将其下载给用户.我试过将Primefaces StreamedContent与p:fileDownload一起使用-但我得到的唯一输出是实际页面的.xhtml源.我可以使用日志语句在返回流之前显示StreamedContent的内容,并且可以在那里正确看到我的XML代码,但是下载的文件始终具有页面源. (我还尝试了许多其他方法,包括下载jpg文件,更改Bean以直接生成响应并通过h:commandButton中的操作调用该方法-始终获取页面源!).
When a button is pressed I need to generate XML and download it to the user. I've tried using primefaces StreamedContent with p:fileDownload - but the only output I ever get is the .xhtml source of the actual page. I can use log statements to display the contents of the the StreamedContent before returning it and I can see my XML code correctly there, but the downloaded file always has the page source instead. (I've tried lots of other ways as well, tied downloading a jpg file, changing the bean to generate a response directly and calling the method through the action in the h:commandButton - always get the page source!).
这是我的.xhtml:
Here's my .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方法:
And the backing bean methods :
public StreamedContent getOrder() {
...
}
(备用)
public String download() {
...
}
我没有包括方法主体,因为我知道它们返回正确的XML ...这似乎确实是JSF魔术中的东西.这是配置问题吗?
I haven't included the method bodies because I know they return proper XML... it really seems to be something in the JSF magic. Is this a configuration issue or something?
谢谢!
更新 好的-我已经从代码中剥离了所有内容,就这样:
UPDATE OK - I've stripped everything out of my code so it's just this :
<?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,甚至重新启动我的盒子).
I've checked my source image file and it's not corrupt. BalusC's code worked for a single try, then I substituted and XML file for the current jpg, changed the MIME type and nothing has worked since. It's as if something bad has tripped in tomcat and I can't get it out or reset it (I've tried cleaning tomcat through eclipse, manually, even rebooted my box).
这是一个真正的装腔作势者.
this is a real poser.
更新: 我已经开始日食干净-没运气.我真的没有主意.我必须认为这是某处的配置,因为我知道这段代码可以工作(我已经看过).
UPDATE : I've started eclipse clean - no luck. I'm really out of ideas. I have to think this is a configuration somewhere, because I know this code can work (I've seen it).
推荐答案
鉴于没有其他人(甚至不是强大的BalusC
)都回答了,我将其发布为评论.
Given that nobody else (not even the mighty BalusC
) has answered, I am posting it as a comment.
关于下载方法,请再次 The BalusC博客.如果您有空闲时间,值得浏览一下.
As how to download, again the BalusC blog. Worth browsing a little if you have spare time.
关于浏览器如何管理它的问题,取决于浏览器的处理方式,无论如何,大多数人都应该尊重Content-Disposition
标头.在示例中更改此行
About the issue with how the browser manages it, it depends of browser handling, anyway most should honor the Content-Disposition
header. Change this line in the example
response.setHeader("Content-Disposition", "inline; filename=\"" + getFileName() + "\"");
到
response.setHeader("Content-Disposition", "attachment; filename\"" + getFileName() + "\"");
这篇关于JSF2下载文件返回xhtml页面源代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!