问题
Using a commandButton in a jsf Page to download a file. Using: JSF & Richfaces.
I have a table (extends ExtendedDataModel implements Modifiable, Serializable) with some data and in each row a button "download".
<a4j:commandButton id="getDownload" value="download"
style="margin-left:10px;margin-right:10px;width:100px;"
action="#{controller.download}" immediate="true" ajaxSingle="true">
<f:setPropertyActionListener target="#{controller.idString}" value="#{item.id}" />
</a4j:commandButton>
I have to build the file in the controller:
public void download(){
OutputStream out = null;
....
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
out = response.getOutputStream();
ZipOutputStream zipout = new ZipOutputStream(out);
.....
zipout.close();
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\""+filename+"\"");
out.flush();
....
} finally {
try {
if (out!=null){
out.close();
}
FacesContext.getCurrentInstance().responseComplete();
} catch (IOException e) {
logger.error(e);
}
}
...
}
The Problem started, when I implemented the ExtendedDataModel my self. At first i used h:commandLink, but the controller method was never called... i tried and tried... now the correct method is called, but the (zip) file content is displayed in the page. I want a button/link in the page, which the user can click to download the file. The page itself should not change. Any ideas?
I can create a servlet, but i do not understand why the ExtendedDataModel changed the behavior of the links inside.
Edit1
I used
<h:commandLink id="getDownload" value="download" action="#{controller.download}">
<f:setPropertyActionListener target="#{controller.idString}" value="#{item.id}" />
</h:commandLink>
before. It works with the "normal" richfaces table, but not when i used it inside my own table which extends ExtendedDataModel.
Edit 2 - Solution/Workaround
It is impossible to use the h:commandButton, .. Link... whatever inside of the self made table, to download a file. I am now using one button in the table to render a new PanelGroup and a second button inside of the new PanelGroupt to download the file. I googled a lot for this, seems like a rich faces bug.
回答1:
You can't download a file by ajax request. Replace a4j:commandButton
by h:commandButton
.
Update as per your question update: to get command links/buttons inside an UIData
component such as <h:dataTable>
, <rich:dataTable>
, etc to work, you need to ensure that the bean which is holding the data model (whatever is behind the value
attribute of the UIData
component) is preserving exactly the same data model during the request of the form submit. If you want to keep your bean request scoped, then the easiest way is to reference the bean in an <a4j:keepAlive>
tag.
回答2:
<h:commandButton id="getDownload" value="download" action="#{controller.download()}" >
</h:commandButton>
public class Controller {
OutputStream out = null;
String filename = "ali.pdf";
public void download() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
out = response.getOutputStream();
ZipOutputStream zipout = new ZipOutputStream(out);
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\""+filename+"\"");
out.flush();
try {
if (out != null) {
out.close();
}
FacesContext.getCurrentInstance().responseComplete();
} catch (IOException e) {
}
}
来源:https://stackoverflow.com/questions/4335849/using-a-commandbutton-in-a-jsf-page-to-download-a-file