GWT FileUpload with Progress Listener

795 views
Skip to first unread message

confile

unread,
Nov 27, 2013, 10:02:48 AM11/27/13
to google-we...@googlegroups.com

 want to observe the upload percentage of a file upload from GWT.

In JavaScript you can use a XMLHttpRequest and add an event listener like this:

var oReq = new XMLHttpRequest();

oReq.upload.addEventListener("progress", updateProgress, false);

// progress on transfers from the server to the client (downloads)
function updateProgress (oEvent) {
  if (oEvent.lengthComputable) {
    var percentComplete = oEvent.loaded / oEvent.total;
    // ...
  } else {
    // Unable to compute progress information since the total size is unknown
  }
}

(The above code is from here.)

This is also done very easily in jQuery as:

 var $request = $.ajax({
      xhr: function() {
        xhrNativeObject = new window.XMLHttpRequest();
        //Upload progress
        xhrNativeObject.upload.addEventListener("progress", function(event) { ... }
      }
 });

I want to do the same with GWT. I could use a RequestBuilder to send a request, but this is only a high level wrapper around the XMLHttpRequest JavaScriot object. Another possibility would be to use the GWT XMLHttpRequest class which is a JSNI wrapper of the JavaScript XMLHttpRequest.

My problem:

How can I add a progress listener to the XMLHttpRequest or the RequestBuilder?

Jens

unread,
Nov 27, 2013, 10:51:45 AM11/27/13
to google-we...@googlegroups.com
Well if you already know the concept of JSNI then you can use it to add a listener to GWT's XMLHttpRequest as its an ordinary JavaScriptObject. You either extend it or create a utility method. Something along these lines (probably not fully correct):

public native void setProgressListener(MyProgressListener p) /*-{
  this.upload.addEventListener("progress", function(event) {
    p.@com.example.progress.MyProgressListener::onProgress(II)(event.loaded, event.total);
  }, false);
}-*/;

A utility method would have an additional XMLHttpRequest parameter and use request.upload instead of this.upload.

Don't forget to cleanup the event listener after you are done. Also note that XMLHttpRequest.create() can return an IE specific object which might not support the progress feature or which requires you do register the listener differently. So your implementation might be a bit more complicated depending on your browser support requirements.

-- J.

confile

unread,
Nov 27, 2013, 12:42:20 PM11/27/13
to google-we...@googlegroups.com
Hi Jens, 

thanks for your help. I know the concept but did not fully understand you. 

1. What do you mean by: "Don't forget to cleanup the event listener after you are done."?

2. Did I get you right on the following. Since I use the progress for file upload I have to use a FormPanel. 

my progress listener class would be like: 

class MyProgressListener {
      void onProgress(int loaded, int total) {
         // so something with the data
      }
}

then I would do something like: 

final FormPanel form = new FormPanel();
form.setAction("/myFormHandler");
form.setEncoding(FormPanel.ENCODING_MULTIPART); 
form.setMethod(FormPanel.METHOD_POST);

    VerticalPanel panel = new VerticalPanel();
    form.setWidget(panel);

FileUpload upload = new FileUpload();
upload.setName("file");
panel.add(upload);

// Add a 'submit' button.
    panel.add(new Button("Submit", new ClickHandler() {
      public void onClick(ClickEvent event) {
        form.submit();
      }
    }));


3. How do I integrate the setProgressListener method in the FormPanel?

Thanks for help.

Juan Pablo Gardella

unread,
Nov 27, 2013, 12:49:42 PM11/27/13
to google-we...@googlegroups.com
See https://code.google.com/p/google-web-toolkit/issues/detail?id=624 comment 23. I've implemented a file upload with a listener and had this problem and solved it using the workaround described there.

Juan


2013/11/27 confile <michael....@googlemail.com>

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/groups/opt_out.

confile

unread,
Nov 27, 2013, 3:11:08 PM11/27/13
to google-we...@googlegroups.com
I did not seen how to implement the progress listener in this post. Could you please post an example?


2013/11/27 confile <michael....@googlemail.com>
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsub...@googlegroups.com.

Thomas Broyer

unread,
Nov 28, 2013, 6:20:21 AM11/28/13
to google-we...@googlegroups.com
Have you checked Elemental? AFAICT, everything's there already.

confile

unread,
Nov 28, 2013, 12:42:31 PM11/28/13
to google-we...@googlegroups.com
Yes, but I do not get how to use it. Can you help me with this please?

Jim Douglas

unread,
Nov 28, 2013, 1:47:38 PM11/28/13
to google-we...@googlegroups.com
I do this in the FormPanel onSubmit:

    private static final int PROGRESS_DELAY_MSEC = 1000;

    private static final int PROGRESS_UPDATE_MSEC = 1000;

    private Timer m_progressUpdateTimer;


        m_progressUpdateTimer = new Timer()

        {

            @Override

            public void run()

            {

                requestProgressUpdate();

            }

        };

        m_progressUpdateTimer.schedule(PROGRESS_DELAY_MSEC);

...

    private void requestProgressUpdate()

    {

        if (DEBUG)

        {

            Log.log(Duration.currentTimeMillis()/1000 + " requestProgressUpdate");

        }

        RequestBuilder builder = new RequestBuilder(GET, FILE_UPLOAD_SERVLET);

        try

        {

            builder.sendRequest(null, new RequestCallback()

            {

                @Override

                public void onResponseReceived(Request p_request,

                                               Response p_response)

                {

                    m_progress.setVisible(true);

                    if (p_response.getStatusCode() == Response.SC_OK)

                    {

                        String text = p_response.getText();

                        if (DEBUG)

                            m_status.setHTML(text);

                        if (m_progressUpdateTimer != null && text.length() > 0)

                            updateProgress(text);

                        if (DEBUG)

                        {

                            Log.log(Duration.currentTimeMillis()/1000

                               + " onResponseReceived " + text + " (OK)");

                        }

                    }

                    else

                    {

                        String text = p_response.getStatusText();

                        m_status.setHTML(text);

                        if (DEBUG)

                        {

                            Log.log(Duration.currentTimeMillis()/1000

                               + " onResponseReceived " + text + " ("+p_response.getStatusCode()+")");

                        }

                    }

                    if (m_progressUpdateTimer != null && isAttached())

                        m_progressUpdateTimer.schedule(PROGRESS_UPDATE_MSEC);

                }

                @Override

                public void onError(Request p_request, Throwable p_e)

                {

                    m_progress.setVisible(true);

                    m_status.setText(p_e.getMessage());

                    if (m_progressUpdateTimer != null && isAttached())

                        m_progressUpdateTimer.schedule(PROGRESS_UPDATE_MSEC);

                    if (DEBUG)

                    {

                        Log.log(Duration.currentTimeMillis()/1000

                           + " onError " + p_e.getMessage());

                    }

                }

            });

        }

        catch (RequestException e)

        {

            m_progress.setVisible(true);

            m_status.setText(e.getMessage());

            if (DEBUG)

            {

                Log.log(Duration.currentTimeMillis()/1000

                   + " RequestException " + e.getMessage());

            }

        }

    }


    private void updateProgress(String p_text)

    {

        try

        {

            Document xml = XMLParser.parse(p_text);

            Integer item = intValue(xml, "item");

            if (item == null)

            {

                m_progress.setItem(null);

            }

            else

            {

                // form item 1 is the id, items 2+ are the files.

                String filename = null;

                if (item > 1 && item - 2 < m_uploadFilelist.size())

                    filename = m_uploadFilelist.get(item - 2);

                m_progress.setItem(filename);

            }

            Integer percent_complete = intValue(xml, "percent_complete");

            if (percent_complete != null)

            {

                m_progress.setProgress(percent_complete.doubleValue());

            }

            if (DEBUG)

            {

                Integer bytes_read = intValue(xml, "bytes_read");

                Integer content_length = intValue(xml, "content_length");

                String progress = "Uploaded " + bytes_read + " of "

                        + content_length + ": " + percent_complete + "%";

                m_status.setText(progress);

            }

        }

        catch (Exception e)

        {

            m_status.setText(e.getMessage());

            if (DEBUG)

            {

                Log.log(Duration.currentTimeMillis()/1000

                   + " updateProgress " + e.getMessage());

            }

        }

    }


    private Integer intValue(Document p_xml, String p_tagname)

    {

        try

        {

            NodeList list = p_xml.getElementsByTagName(p_tagname);

            if (list.getLength() > 0)

            {

                Node node = list.item(0);

                list = node.getChildNodes();

                node = list.item(0);

                String value = node.getNodeValue();

                if (value != null)

                    return Integer.valueOf(value);

            }

        }

        catch (Exception e)

        {

            m_status.setText(e.getMessage());

        }

        return null;

    }


    private static class UploadProgressBar extends ProgressBar

    {

        private String m_item;


        public UploadProgressBar()

        {

            super();

        }


        public void setItem(String p_item)

        {

            m_item = p_item;

        }


        @Override

        protected String generateText(double curProgress)

        {

            if (m_item == null)

                return (int)(100 * getPercent()) + "%";

            else

                return m_item + " " + (int)(100 * getPercent()) + "%";

        }

    }



doGet in my FileUploadServlet does this:


    @Override

    protected void doGet(HttpServletRequest p_request,

                         HttpServletResponse p_response)

        throws ServletException, IOException

    {

        if (DEBUG)

            System.err.println("\n" + System.nanoTime() + " doGet request "

                + p_request.getContentType() + " " + p_request.getServletPath());


        HttpSession session = p_request.getSession();

        if (session == null)

            return;


        FileUploadProgress progress =

            (FileUploadProgress)session.getAttribute("progress");

        if (progress == null)

            return;


        long bytesRead = progress.getBytesRead();

        long contentLength = progress.getContentLength();

        int item = progress.getItem();


        p_response.setContentType("text/xml");


        StringBuffer buffer = new StringBuffer();

        buffer.append("<?xml version=\"1.0\"?>\n");

        buffer.append("<response>\n");

        buffer.append("\t<item>").append(item)

              .append("</item>\n");

        buffer.append("\t<bytes_read>").append(bytesRead)

              .append("</bytes_read>\n");

        buffer.append("\t<content_length>").append(contentLength)

              .append("</content_length>\n");


        long percentComplete;

        if (bytesRead < contentLength && contentLength != 0)

        {

            percentComplete = ((100 * bytesRead) / contentLength);

        }

        else

        {

            percentComplete = 100;

            session.setAttribute("progress", null);

        }


        buffer.append("\t<percent_complete>").append(percentComplete)

              .append("</percent_complete>\n");

        buffer.append("</response>\n");


        PrintWriter out = p_response.getWriter();

        out.println(buffer.toString());

        out.flush();

        out.close();

    }


FileUploadProgress uses this Apache Commons package:


import org.apache.commons.fileupload.ProgressListener;


public class FileUploadProgress implements ProgressListener

{

    private volatile long m_bytesRead;

    private volatile long m_contentLength;

    private volatile int m_item;


    public FileUploadProgress()

    {

        super();

    }


    @Override

    public void update(long p_bytesRead, long p_contentLength, int p_item)

    {

        m_bytesRead = p_bytesRead;

        m_contentLength = p_contentLength;

        m_item = p_item;

    }


    public long getBytesRead()

    {

        return m_bytesRead;

    }


    public long getContentLength()

    {

        return m_contentLength;

    }


    public int getItem()

    {

        return m_item;

    }

}

confile

unread,
Dec 5, 2013, 7:09:59 AM12/5/13
to google-we...@googlegroups.com
Great thank you I will check that.
Reply all
Reply to author
Forward
0 new messages