Вопрос

I'm uploading images using <p:fileUpload> as follows.

<p:outputLabel for="txtCatImage" value="#{messages['category.image']}"/>

<p:fileUpload id="txtCatImage" mode="advanced" 
              dragDropSupport="true" required="true"
              sizeLimit="1000000" fileLimit="1" multiple="false" 
              cancelLabel="#{messages['fileupolad.cancelLabel']}"
              label="#{messages['fileupolad.label']}"
              uploadLabel="#{messages['fileupolad.uploadLabel']}" 
              allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
              invalidFileMessage="#{messages['fileupolad.invalidFileMessage']}"
              invalidSizeMessage="#{messages['fileupolad.invalidSizeMessage']}"
              fileLimitMessage="#{messages['fileupolad.fileLimitMessage']}"
              fileUploadListener="#{categoryManagedBean.fileUploadListener}"/>
<p:message for="txtCatImage" showSummary="false"/>

<p:commandButton id="btnSubmit" update="panel messages"
                 actionListener="#{categoryManagedBean.insert}"
                 value="#{messages['button.save']}"/>

fileUploadListener in the corresponding managed bean decorated with @ViewScoped is as follows.

//This is just a utility method and can be placed anywhere in the application.
private static boolean validateImageDimensions(byte[] bytes) throws IOException {
    BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(bytes));        
    return bufferedImage.getHeight()>=750 || bufferedImage.getWidth()>=650;
}

public void fileUploadListener(FileUploadEvent event) throws IOException {
    UploadedFile uploadedFile = event.getFile();
    byte[] bytes = IOUtils.toByteArray(uploadedFile.getInputstream());

    if(!Utility.validateImageDimensions(bytes)) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.validationFailed();
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Message summary", "Error message");
        FacesContext.getCurrentInstance().addMessage(event.getComponent().getClientId(context), message);
    }
    else {//Do something.}
}

The listener of <p:commandButton> is as follows which should not be invoked, if validation in fileUploadListener() fails.

public void insert() {
    //Code to invoke an EJB to insert a new row along with the uploaded file.
}

If if(!Utility.validateImageDimensions(bytes)) is evaluated to true then, the action listener of <p:commandButton> (the insert() method above) should not be invoked but it is invoked and this kind of validation implies no effect at all.

As already stated, PrimeFaces file upload validators don't work.

What am I doing wrong here? What is the way to validate dimensions of an uploaded image?

Это было полезно?

Решение

Your concrete problem is caused because the upload action took place in a different HTTP request than the save action. You first choosed the file and then pressed Upload (request #1) and then the Save button (request #2), right? The network monitor in browser's builtin developer toolset (press F12) should also confirm it. The FacesContext#validationFailed() is in essence request scoped, like the FacesContext itself. So, when you set it during the request which invokes the upload action, then it's just "reset" during the request which invokes the save action.

This is indeed somewhat awkward. As the <p:fileUpload mode="advanced"> doesn't support Validators, as you already found out, there's not really a clean solution to this problem. You should be fiddling with a view scoped bean property to maintain the validation state across the requests on the same view.

private boolean validationFailed;

public void fileUploadListener(FileUploadEvent event) throws IOException {
    // ...
    validationFailed = !Utility.validateImageDimensions(bytes);

    if (validationFailed) {
        // Add message.
    }
    else {
        // Process upload.
    }
}

public void insert() {
    if (validationFailed) {
        // Add message.
    }
    else {
        // Process insert.
    }
}

By the way, I'd rather not set those messages as FATAL, but as ERROR. The enduser is namely capable of fixing it all by itself.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top