小编典典

h:commandButton多个操作:下载文件并渲染ajax表

ajax

我目前有2个命令按钮和一个列表框。根据列表框的选择,生成的结果可以显示在可下载的文件中或呈现为HTML表。该getFile()代码基于BalusC的PDF
Handling教程
,而getTable()set resultTable

<h:form>
<fieldset>
    <h:selectManyListbox id="listbox" value="#{form.items}">
        <f:selectItems value="#{form.allItems}">
    </h:selectManyListbox>
</fieldset>
<h:commandButton value="Get File" action="#{form.getFile}">
<h:commandButton value="Get Table" action="#{form.getTable}">
    <f:ajax render="result_table" execute="listbox" />
</h:commandButton>
<h:panelGrid id="result_table">
    <table>
        <thead></thead>
        <tbody>
            <ui:repeat var="table" value="#{form.resultTable}">
            </ui:repeat>
        </tbody>
    </table>
</h:panelGrid>

到目前为止,两个按钮都可以正常工作。但是,我想将两个动作组合为一个按钮。当我用一个可以触发两个动作的按钮进行测试时,什么也没发生(没有文件另存为对话框或表)。这是因为一个动作是ajax还是另一个动作以ajax结尾facesContext.responseComplete();

<h:commandButton value="Get Both" action="#{form.getBoth}">
    <f:ajax render="result_table" execute="listbox" />
</h:commandButton>

getBoth() {
    getTable();
    getFile();
}

另外,我想要一个复选框,如果选中该复选框,则会弹出另存为对话框并呈现表格。如果未选中,则仅呈现表。


阅读 228

收藏
2020-07-26

共1个答案

小编典典

不幸的是,HTTP无法实现。每个请求只能发送回一个响应。您不能将包含PDF文件和ajax响应的响应合并为一个响应。由于这是HTTP限制,因此JSF不能为您做任何事情。另外,根本不可能使用Ajax下载文件,因为由于安全限制,JavaScript不能强制浏览器弹出“
另存为” 对话框,也不能对本地磁盘文件系统进行任何访问。

一种解决方法是单击一次第二个请求返回的位置时,在一次单击按钮上触发 两个 HTTP请求,以使另一个请求Content-Disposition: attachment的响应保持不变。您可以通过onclick在命令按钮上添加一个来实现。

<h:commandButton onclick="window.location='/context/pdfservlet/filename.pdf'">

并创建一个大致类似于此FileServlet示例的PDF
servlet
。如您所见,由此不可能调用JSF操作。您必须将PDF下载方法重构为可完成方法HttpServlet工作的类doGet()。对于JSF托管bean和servlet之间的任何必要通信,您可以使用会话范围或通过请求路径或参数传递所需的信息(只是PDF文件标识符?)。

2020-07-26