在jsf页面中使用commandButton下载文件

时间:2010-12-02 14:09:00

标签: java jsf richfaces

使用jsf页面中的commandButton下载文件。使用:JSF& RichFaces的。

我有一个表(扩展ExtendedDataModel实现Modifiable,Serializable)和一些数据,每行都有一个“下载”按钮。

<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>

我必须在控制器中构建文件:

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);
    }

}
...
}

当我实现ExtendedDataModel时,问题就开始了。 起初我使用了h:commandLink,但是控制器方法从未被调用过......我试过试过......现在调用了正确的方法,但是(zip)文件内容显示在页面中。我想在页面中有一个按钮/链接,用户可以单击该链接下载文件。页面本身不应该改变。有任何想法吗?

我可以创建一个servlet,但我不明白为什么ExtendedDataModel改变了里面链接的行为。

EDIT1

我用过

<h:commandLink id="getDownload" value="download" action="#{controller.download}">                                                       
                            <f:setPropertyActionListener target="#{controller.idString}" value="#{item.id}" />                              
                        </h:commandLink>

之前。它适用于“普通”richfaces表,但不是当我在我自己的表中使用它扩展ExtendedDataModel时。

编辑2 - 解决方案/解决方法

无法使用h:commandButton,.. Link ...在自制表内部,下载文件。我现在使用表中的一个按钮来渲染新的PanelGroup和新PanelGroupt内的第二个按钮来下载文件。 我为此搜索了很多,似乎是一个富有的面孔虫。

2 个答案:

答案 0 :(得分:10)

您无法通过ajax请求下载文件。将a4j:commandButton替换为h:commandButton


根据您的问题更新

更新:要使UIData组件(例如<h:dataTable><rich:dataTable>等)内的命令链接/按钮正常工作,需要确保持有数据模型的bean(value组件的UIData属性后面的任何内容)在表单提交请求期间保留完全相同的数据模型。如果要保持bean请求作用域,那么最简单的方法是在<a4j:keepAlive>标记中引用bean。

答案 1 :(得分:4)

<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) {

    }

}