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 theFacesContext
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 supportValidator
s, 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.By the way, I'd rather not set those messages as
FATAL
, but asERROR
. The enduser is namely capable of fixing it all by itself.