Display p: file upload image to p: graphicImage preview without saving it

I am using PrimeFaces 5.3 <p:fileUpload> to load a PNG image, and I would like to display it in <p:graphicImage> before saving to the database.

Here's MCVE:

 <h:form enctype="multipart/form-data"> <p:fileUpload value="#{bean.uploadedFile}" mode="simple" /> <p:graphicImage value="#{bean.image}" /> <p:commandButton action="#{bean.preview}" ajax="false" value="Preview" /> </h:form> 

 private UploadedFile uploadedFile; public UploadedFile getUploadedFile() { return uploadedFile; } public void setUploadedFile(UploadedFile uploadedFile) { this.uploadedFile = uploadedFile; } public void preview() { // NOOP for now. } public StreamedContent getImage() { if (uploadedFile == null) { return new DefaultStreamedContent(); } else { return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png"); } } 

Errors that occur on the backup bean and the image will not be uploaded and displayed on the interface. The client mentions that the image returned 404 not found error.

+5
source share
1 answer

Your problem is doubled. This failed because the contents of the downloaded file are the scope of the request and because the image is being requested in another HTTP request. To better understand the inner workings, carefully read the answers to the following related Q & A questions:

To solve the first problem, you need to read the contents of the downloaded file immediately in the action method associated with the submit form. In your particular case, it will look like this:

 private UploadedFile uploadedFile; private byte[] fileContents; public void preview() { fileContents = uploadedFile.getContents(); } // ... 

To solve the second problem, it is best to use a data URI scheme. This allows you to render the image directly in the same answer, and therefore you can safely use the @ViewScoped bean without running into context inactive problems or saving byte[] in a session or disk to enable the image function in another request. Browser support by data URI scheme is currently pretty good. Replace all <p:graphicImage> below:

 <ui:fragment rendered="#{not empty bean.uploadedFile}"> <img src="data:image/png;base64,#{bean.imageContentsAsBase64}" /> </ui:fragment> 

 public String getImageContentsAsBase64() { return Base64.getEncoder().encodeToString(imageContents); } 

Note. I assume Java 8 is available to you as java.util.Base64 was introduced only in this version. If you are using an older version of Java, use DatatypeConverter.printBase64Binary(imageContents) .

If you use the JSF OmniFaces utility library , you can also just use it <o:graphicImage> , which contradicts <p:graphicImage> , which can directly refer to the byte[] property and InputStream bean and display the data URI.

 <o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}"> 
+6
source

All Articles