Display total files uploaded on file upload complete - jsf

I know my question is quite basic but I couldn't find anything on SO or Google regarding this.
I am using PrimeFaces and their p:fileUpload component. It is working fine, files are being uploaded. The problem is, after these files are uploaded, I need to show user how many files are uploaded, and not using JavaScript. I need this number in my Backing Bean.
There is one oncomplete attribute but that is for client side callback (which again is JavaScript).
Following is my humble code :)
<p:fileUpload required="true" requiredMessage="No files selected."
mode="advanced"
multiple="true"
dragDropSupport="true"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
update="growlMessage"
fileUploadListener="#{mainForm.fileUploadListener}">
</p:fileUpload>
And here is backing bean:
#ManagedBean
#SessionScoped
public class MainForm {
private int totalImageFiles;
public MainForm() {
this.totalImageFiles = 0;
}
public void fileUploadListener(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
ReaderWriter.ReadWrite(uploadedFile, yourName, yourHomeAddress, totalImageFiles);
totalImageFiles++;
}
}
totalImageFiles is the number that I want to show user. It has the correct values but I don't know how to send another request to retrieve this number.

Just reference it in some output component and ajax-update it.
<p:fileUpload ... update="growlMessage totalImageFiles" />
<h:outputText id="totalImageFiles" value="#{mainForm.totalImageFiles}" />

Related

Strange display of p:fileUpload component

I am trying to use the fileUpload component of PrimeFaces and everything is working BUT an empty error message is displayed when the component appeared with no content and i do not understand why.
And if i add a file to the component is disappeared well but it is still not pretty to have it when the component loads.
// View
<h:form>
<p:fileUpload fileUploadListener="#{bean.handleFileUpload}" />
</h:form>
// ManagedBean
public void handleFileUpload(FileUploadEvent event) {
UploadedFile file = event.getFile();
System.out.println("handleFileUpload : " + file);
}
The managed bean function is well called when I click on the upload button.
Hope some could understand my problem !
Thanks in advance

Display p:fileupload image in p:graphicImage preview without saving it

I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.
Here's a 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");
}
}
No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.
Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:
Display dynamic image from database with p:graphicImage and StreamedContent
How to choose the right bean scope?
To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:
private UploadedFile uploadedFile;
private byte[] fileContents;
public void preview() {
fileContents = uploadedFile.getContents();
}
// ...
To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a #ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with 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 that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.
In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.
<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">

How can I render a file cached in a managed bean?

Current versions: JSF 2.1, RichFaces 4.5.2
I got into the following problem:
I have an upload component in one of my web-pages which is going to upload images:
<h:graphicImage id="uploadedPict" value="__WHAT__?" alt="picture />
<rich:fileUpload id="imageStartUploadComponent"
fileUploadListener="#{MyBean.uploadStartImage}"
acceptedTypes="png,jpg"
immediateUpload="false">
<a4j:ajax event="uploadcomplete" render="uploadedPict" />
</rich:fileUpload>
and the manged bean itself:
public class MyBean{
private UploadedFile detailsImage;
public void uploadStartImage(){
//SETTING detailsImage here
}
//GET, SET, OTHER STUFF
}
I could invoke UploadedFile::getData() method to retrieve binary image data. But how can I render it into the web-page? value attribute is supposed to be assigned with an actual picture's URL. So it seems I'm going to have to write my own servlet...
QUESTION: Is there a way to avoid writing a servlet and render the picture right from managed bean's method returning its binary data?
UPDATE: I need to do this for showing uploaded picture's preview. Maybe there is another way to do that correctly?
You can use <a4j:mediaOutput>:
<a4j:mediaOutput element="img" mimeType="image/jpeg"
createContent="#{bean.paint}" value="#{bean.file}">
</a4j:mediaOutput>
and the paint method:
public void paint(OutputStream stream, Object object) throws IOException {
stream.write(((UploadedFile) object).getData());
stream.close();
}
(check the showcase example)

Include dialog from another file via backing bean

I have a Primefaces project in which I am trying to replicate the behavior of a desktop application. Because of the nature of the desktop application, there are quite a few popup dialogs, which cause the processing of the page to become very slow (initial page load: 10-20 seconds, AJAX requests: 6-10 seconds).
I have separate files for all the dialogs already, and I want to use the backing bean to pop them up as dialogs without having to use <ui:include> in my main files. Is there a way to do this?
e.g.:
<p:commandButton id="showSearchDialog"
action="#{managedBean.showSearchDialog()}"/>
<p:dialog widgetVar="searchDialog">
</p:dialog>
public class ManagedBean {
public void showSearchDialog() {
//Some sort of function that knows to process the contents of searchDialog.xhtml
// and insert it into the relevant <p:dialog>
RequestContext.getCurrentInstance().execute("PF('searchDialog').show()");
}
}
If your goal is to reduce the size of the page, I'd approach it with conditional rendering of the dialog itself as determined by a backing bean property which would be set by the command action:
<p:commandButton id="showSearchDialog"
action="#{managedBean.showSearchDialog()}"
update="dialogs"
oncomplete="PF('searchDialog').show()" />
<h:panelGroup id="dialogs" layout="block">
<p:dialog widgetVar="searchDialog" rendered="#{managedBean.currentDialog eq 'search'}">
<ui:include src="searchDialog.xhtml" />
</p:dialog>
</h:panelGroup>
public class ManagedBean {
private String currentDialog;
public String getCurrentDialog() { return currentDialog; }
public void showSearchDialog() { currentDialog = "search"; }
}
Then you could conditionally render all of your dialogs within the 'dialogs' block and use ajax to refresh the rendered content dynamically.
Another option to consider is using the PrimeFaces Dialog Framework, which allows you to dynamically render an external page at runtime.

rich:fileUpload more file information

I want to upload many files and I have chosen rich:fileUpload control for this.
My problem is that I need to add more information for each file, for example the title I want to appear in the application for that file. How can I do that, and send to the fileUploadListener method in order to use the id?
Based in your question, the RichFaces FileUpload demo has all the info you need to handle file upload for 1 or more files at the same time.
If you want to add more data (like h:inputText values and others), then you should pass them using valueChangeListener instead value tag attribute, because the fileUploadListener is an event that happens within an ajax call, so your UIComponents won't call the setters for the attributes.
Some code to explain the behavior:
<h:panelGrid cols="2">
<h:outputText value="File Title:">
<h:inputText value="#{fileBean.fileTitle}" immediate="false"
valueChangeListener="#{fileBean.valueChangeFileTitle}" />
<h:outputText value="File:">
<rich:fileUpload
fileUploadListener="#{bean.fileUpload}">
</rich:fileUpload>
</h:panelGrid>
The Bean to handle the requests
public class Bean {
private String fileTitle;
public Bean() {
}
//getters and setters...
public String getFileTitle() {
return this.fileTitle;
}
public void setFileTitle(String fileTitle) {
System.out.println("Calling the setter");
this.fileTitle = fileTitle;
}
public void valueChangeFileTitle(ValueChangeEvent e) {
System.out.println("Calling the ValueChangeListener");
fileTitle = (String)e.getNewValue();
}
//this will be invoked by an ajax call
//the setter of the view won't be invoked for fileTitle
//instead, we should take its value using valueChangeListener
public void fileUpload(UploadEvent ue) {
MyFileManager mfm = MyFileManager.getFileManager();
MyFile myFile = new MyFile();
myFile.setTitle(this.fileTitle);
myFile.setName(ue.getUploadItem().getFileName());
myFile.setData(ue.getUploadItem().getData());
mfm.createFile(myFile);
}
}
Also, avoid to use System.out.println calls in your code, I'm doing it so you can understand what method will be called, instead use a Logger like Log4j.

Resources