有条件地提供文件下载或显示导出验证错误消息

Conditionally provide either file download or show export validation error message

我一直在开发 CRUD 应用程序,我需要将数据从数据库导出到 csv 文件。 为了导出,我必须以如下代码所示的方式禁用 ajax:

<p:commandButton value="Export" ajax="false" action="myController.export"/>

在调用的方法中,我创建了文件并通过 OmniFaces 实用方法下载它:

Faces.sendFile(file, true);

用同样的方法,我检查是否确实有任何数据,如果没有任何数据,则显示警告对话框:

RequestContext.getCurrentInstance().showMessageInDialog(new FacesMessage(FacesMessage.SEVERITY_WARN, "Warning!", "No available data for export."));

现在,虽然所有这一切都按预期工作,但问题是因为 ajax 被禁用,对话框无法动态显示,页面会重新加载。如果启用 ajax,对话框会动态显示,但文件下载不会开始。

我一直在尝试通过使用 Monitor download 或强制单击第二个按钮来解决这个问题,但到目前为止我在这件事上没有取得任何进展。

是否有解决此类问题的普遍可接受的方法?

Is there any generally acceptable way of solving issues like this one?

你基本上想先触发一个 ajax 请求并在它的 oncomplete 检查它是否成功,然后触发一个同步请求来下载文件(注意你 can't download files with ajax). You could make use of FacesContext#validationFailed() (or OmniFaces Faces.validationFailed())来标记验证失败状态可通过 PrimeFaces 在 oncomplete 函数上下文中注入的 args 对象获得(请注意 ajax 相关属性如 oncomplete 在 [=28 时不起作用=] 已禁用)。

像这样:

<p:commandButton 
    value="Export" 
    action="#{bean.export}" 
    oncomplete="if (args &amp;&amp; !args.validationFailed) PF('download').jq.click()" />
<p:commandButton 
    widgetVar="download" 
    styleClass="ui-helper-hidden" 
    action="#{bean.download}" ajax="false" />
public void export() {
    // Prepare file locally.

    if (fail) {
        // Show message your way and then set validation failed as below.
        Faces.validationFailed();
    }
}

public void download() throws IOException {
    Faces.sendFile(file, true);

    // Delete local file afterwards?
}

请注意,使用隐藏的 <p:commandButton> 而不是 <p:remoteCommand>,因为后者不支持 ajax="false"