【问题标题】:PrimeFaces <p:fileUpload mode="advanced"> validator not firedPrimeFaces <p:fileUpload mode="advanced"> 验证器未触发
【发布时间】:2020-07-20 00:44:39
【问题描述】:

因为在 primefaces 3.4 中不再存在 fileLimit 我正在尝试解决实现验证器的工作,问题是方法 validate 从未被调用。那是我的验证器:

@FacesValidator(value ="fileLimitValidator")
public class FileLimitValidator implements Validator {

    @Override
    public void validate(final FacesContext context, final UIComponent component,
            final Object value) throws ValidatorException {

        final String fileLimit = (String)component.getAttributes().get("fileLimit");
        final String size = (String)component.getAttributes().get("size");

        if (fileLimit!=null && size!=null) {
            if (Integer.valueOf(size) >= Integer.valueOf(fileLimit)) {
                FacesUtils.throwErrorExceptionFromComponent(component,"fichero_confidencialidad_error");
            }
        }
    }
}

在我的 facelet 中我尝试过:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" >

        <f:validator validatorId="fileLimitValidator"/>
        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

和:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="fileLimitValidator">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

和:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="#{fileLimitValidator}">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

和:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="#{fileLimitValidator.validate}">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

但从不调用 validate 方法。正确的做法是什么?

【问题讨论】:

  • stackoverflow.com/questions/3523998/… 我认为这就是它的样子。我们看起来是您尝试过的事情之一:(),请确保您使用的是正确的导入。然后我会开始怀疑这个组件可能不支持它
  • 我尝试了 与 h:inputText 和方法被调用。

标签: jsf file-upload jsf-2 primefaces validation


【解决方案1】:

根据FileUploadFileUploadRenderer 源代码,只有在使用mode="simple" 时才会调用验证器(注意:这又需要ajax="false" 命令)。高级模式即不会将上传的文件设置为组件的提交值,使其保持null,直到调用监听器方法。只要提交的值为null,就不会调用验证器。

我不确定这是否是故意的。从理论上讲,应该可以将UploadedFile 设置为提交的值并让验证器依赖它。您可能想在PrimeFaces issue tracker 创建增强报告。

同时,尽管它是poor practice,但最好的选择实际上是在fileUploadListener 方法中执行验证。您可以通过FacesContext 触发验证失败添加面孔消息,如下所示:

if (fail) {
    context.validationFailed();
    context.addMessage(event.getComponent().getClientId(context), new FacesMessage(
        FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
}

否则,您需要为&lt;p:fileUpload&gt; 创建一个自定义渲染器,该渲染器在decode() 期间设置提交的值(但我不保证它会在实践中起作用,您可能会偶然发现一个特殊的问题,这可能是 PrimeFaces 最初没有像那样实现它的原因)。

顺便说一句,您的第一次和第二次验证人尝试都是正确的。仅当您使用 @ManagedBean 而不是 @FacesValidator (which is often done when injection of an @EJB is mandatory — which isn't possible in a @FacesValidator) 时,第三次尝试才有效。第四次尝试无效。

【讨论】:

  • @BalusC,为了验证(例如,我需要至少上传一个文件):如果p:fileUpload 在表单中,并且只有@987654343 表单,您如何触发该 fileUploadListener 事件@ 是否存在于用户面前?
【解决方案2】:

为了在高级模式 (ajax) 中验证所需的 primefaces 文件上传,可以使用:

<f:metadata>
    <f:event listener="#{bean.processValidations()}" type="postValidate" />
</f:metadata>

bean.processValidations() 方法的实现大致如下:

public void processValidations() {
        FacesContext context = FacesContext.getCurrentInstance();
        UIInput fileUploadComponent = fileUploadsBean.getFileUploadComponent();
        if (fileUploadComponent!=null && !isFileUploaded()) {
            fileUploadComponent.setValid(false);
            context.addMessage(fileUploadComponent.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
            context.validationFailed();
        }
    }

fileUploadsBean 将是一个 REQUEST 范围的 CDI bean(不适用于标准 JSF ManagedBeans),您将其注入到定义了 processValidations() 方法的 bean 中,方法 fileUploadsBean.getFileUploadComponent() 返回 primefaces 文件上传组件(您将为此使用&lt;p:fileUpload binding="#{fileUploadsBean.fileUploadComponent}" ...&gt;)。 isFileUploaded() 方法将确定文件是否已上传(可能只是对您从 fileUploadListener 填充的成员变量进行空检查)。

如果您想突出显示文件上传按钮,您当然可以有条件地添加一个 styleClass,然后您可以使用它来添加红色边框。

styleClass="#{fileUploadsBean.fileUploadComponent.valid ? '' : 'validationFailed'}"

因此,primefaces 文件上传的验证失败消息将与所有其他 jsf 验证消息一起显示。您可能在维护验证消息的顺序时遇到问题(将始终在最后),但是在用户处理来自不同字段的所有标准 jsf 验证消息以及您在支持 bean 中的操作之后,它仍然优于显示失败的上传文件验证终于到了。

【讨论】:

  • 非标准验证 IMO 的最佳方法
猜你喜欢
  • 2012-02-05
  • 1970-01-01
  • 2012-04-15
  • 2011-01-12
  • 2023-03-03
  • 2023-03-10
  • 1970-01-01
  • 2014-05-11
相关资源
最近更新 更多