AJAX+JSF components achieve High-performance file uploads (2)

Source: Internet
Author: User
Tags add file upload html file upload implement reset return string
ajax|js| Performance We will implement an AJAX-capable component that not only implements the actual process of uploading files to the server, but also "real-time" monitoring of file uploads. (iv) Progressmonitorfileitem class

public class Progressmonitorfileitem extends Diskfileitem {
Private Progressobserver Observer;
Private Long passedinfilesize;
...
Private Boolean Isformfield;
...
@Override
Public OutputStream Getoutputstream () throws IOException {
OutputStream baseoutputstream = super.g Etoutputstream ();  
if (Isformfield = = False) {
return new Bytescountingoutputstream (Baseoutputstream);
}else{return Baseoutputstream;}
}
...  
Private class Bytescountingoutputstream extends outputstream{
Private long previousprogressupdate
Private OutputStream base;
Public Bytescountingoutputstream (OutputStream ous) {base = ous;}
...   
private void fireprogressevent (int b) {
Bytesread + = b;
...
Double progress = ((double) (bytesread)/passedinfilesize);
Progress *= 100.0
Observer.setprogress ();
}
}
}

Progressmonitorfileitem wraps the default outputstream of Diskfileitem into a bytescountingoutputstream, This can update the associated progressobserver each time a certain number of bytes are read.

(v) AJAX-enabled JavaServer Faces (JSF) Upload components

This component is responsible for generating HTML file upload tags, displaying a progress bar to monitor file uploads, and generating components that need to be displayed once the file is uploaded successfully. One of the main advantages of using JavaServer faces to implement this component is that most of the complexity is hidden. Developers only need to add component tags to the JSP, and then the component will be responsible for all Ajax and related progress bars to monitor the details. The following JSP code fragment is used to add the upload component to the page.

Value= "#{uploadpagebean.uploadedfile}"
uploadicon= "Images/upload.png"
Styleclass= "Progressbardiv"
Progressbarstyleclass= "ProgressBar"
Cellstyleclass= "Progressbarcell"
Activestyleclass= "Progressbaractivecell" >
<%--below is the component that will become visible once the file upload is completed--%>

Value= "file uploaded successfully."/>


Image= "Images/reset.png"/>


Image= "Images/continue.png"/>



The Value property of the file upload component needs to be bound to a bean with an attribute with a fileitem. The component is displayed only if the file is successfully received by the server.

   third, the realization of Ajax file upload components

Essentially, uploading a component or generating a complete self, or, in the case of an AJAX request, only generates part of the XML to update the status of the progress bar on the page. To prevent the JavaServer faces from generating the complete component tree (which can result in unnecessary load), We also need to implement a Phaselistener (Pagephaselistener) to cancel the other parts of the faces request processing-If an AJAX request is encountered. I've omitted all the discussion about standard configurations (Faces-config.xml and tag libraries) in this article because they are fairly straightforward and have been discussed before, and are all contained in the source code accompanying this article, which you can analyze in detail.

(i) Ajax file Upload Component Builder

The implementation of this component and tag class is simpler. A large number of logic is included in the builder, specifically, it is responsible for the following:

· Encode the entire upload component (and the full HTML file upload tag), the component to display when the file is uploaded, and the client JavaScript code that implements the AJAX request.

· Handle partially AJAX requests appropriately and send back the necessary XML.

· Decode a file upload and set it to a Fileitem instance.

(ii) encoding the entire upload component

As mentioned earlier, the file Upload component consists of three phases. During the entire encoding of the component, we will analyze the encoding for these three phases in detail. Note that the visualization of the component on the page (using CSS Display) attributes will be controlled by Ajax JavaScript.

(iii) Phase I

Figure 5 shows the first phase of the upload component.


Figure 5. Select File Upload


In the first phase, we need to generate HTML file upload tags and click the upload button when the corresponding execution code. Once the user clicks on the Upload button, the form is submitted and initialized to the second phase by an IFRAME (to prevent the page from blocking). The following is part of the generated code:

File Upload Component
Writer.startelement ("input", component);
Writer.writeattribute ("type", "file", null);
Writer.writeattribute ("Name", Component.getclientid (context), "id");
Writer.writeattribute ("id", Component.getclientid (context), "id");
if (Input.getvalue ()!= null) {
If available, the file name is generated.
Fileitem filedata = (fileitem) input.getvalue ();
Writer.writeattribute ("Value", Filedata.getname (), Filedata.getname ());
}
Writer.endelement ("input");
String Iconurl = Input.getuploadicon ();
Generate images and attach JavaScript events to them.
Writer.startelement ("div", component);
Writer.writeattribute ("Style", "display:block;width:100%;text-align:center;", "style");
Writer.startelement ("img", component);
Writer.writeattribute ("src", Iconurl, "src");
Writer.writeattribute ("type", "image", "type");
Writer.writeattribute ("Style", "cursor:hand;cursor:pointer;", "style");
UIForm form = Facesutils.getform (context,component);
if (form!= null) {
String Getformjs = "document.getElementById ('" + form.getclientid (context) + "')";
String Jsfriendlyclientid = Input.getclientid (context). Replace (":", "_");
Set the encoding of the form to multipart for file uploads, and pass an IFRAME
To submit its contents. The second phase of the component is also initialized after 500 milliseconds.
Writer.writeattribute ("onclick", Getformjs + ". encoding= ' Multipart/form-data ';" +
Getformjs + ". target= '" + Iframename + "" + Getformjs + ". Submit ();" +
Getformjs + ". encoding= ' application/x-www-form-urlencoded ';" +
Getformjs + ". target= ' _self ';" +
"SetTimeout (' refreshprogress" + Jsfriendlyclientid + "(); ';"; ", null);
}
...
Writer.endelement ("img");
Now implement the IFRAME we are going to submit the file/form to.
Writer.startelement ("iframe", component);
Writer.writeattribute ("id", iframename, NULL);
Writer.writeattribute ("name", Iframename,null);
Writer.writeattribute ("Style", "display:none;", null);
Writer.endelement ("iframe");
Writer.endelement ("div");
Writer.endelement ("div"); Phase 1 over

(iv) Phase II

The second stage is a progress bar and label showing the current percentage, as shown in Figure 6. The progress bar is implemented as a DIV tag with 100 inline span tags. These will be set by Ajax JavaScript based on the response from the server.


Figure 6. Uploading files to the server

Writer.startelement ("div", component);
Writer.writeattribute ("id", Input.getclientid (context) + "_stage2", "id");
...
Writer.writeattribute ("Style", "Display:none", "style");
String Progressbarid = Component.getclientid (context) + "_progressbar";
String Progressbarlabelid = Component.getclientid (context) + "_progressbarlabel";
Writer.startelement ("div", component);
Writer.writeattribute ("id", Progressbarid, "id");
String Progressbarstyleclass = Input.getprogressbarstyleclass ();
if (Progressbarstyleclass!= null)
Writer.writeattribute ("Class", Progressbarstyleclass, "class");
for (int i=0;i<100;i++) {
Writer.write (" ");
}
Writer.endelement ("div");
Writer.startelement ("div", component);
Writer.writeattribute ("id", Progressbarlabelid, "id");
...
Writer.endelement ("div");
Writer.endelement ("div"); Phase 2 over

(v) Phase three

Finally, as stage three, once the file is uploaded successfully, the component that needs to be displayed is generated, as shown in Figure 7. These are implemented in the Encodechildren method of the generator.


Figure 7. Upload Complete

public void Encodechildren (Facescontext context,
UIComponent component) throws IOException {
Responsewriter writer = Context.getresponsewriter ();
Uifileupload input = (uifileupload) component;
Once the file is uploaded successfully, handle the child nodes that will be displayed
Writer.startelement ("div", component);
Writer.writeattribute ("id", Input.getclientid (context) + "_stage3", "id"); Stage 3.
if (input.getvalue () = null) {
Writer.writeattribute ("Style", "display:none;", null);
}else{
Writer.writeattribute ("Style", "Display:block", null);
}
List children = Input.getchildren ();
for (UIComponent Child:children) {
Facesutils.encoderecursive (Context,child);
}
Writer.endelement ("div"); Phase 3 over
}


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.