Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Multipart HTTP forms submitter - With Progress Information

0.00/5 (No votes)
27 Jan 2006 1  
Submit multipart HTTP requests from Java and display information about the upload progress
Sample Image - ClientHTTPRequest2.gif

Introduction

In one of my projects, I had to be able to submit a data to the Web server using HTTP. The issue was that this data was multipart – that is, a combination of binary data and text data. So a simple GET or POST call would not have been sufficient. To my rescue, came Vlad Patryshev’s class: ClientHTTPRequest. This highly versatile class allows you to easily submit multipart data via HTTP. However it was missing one thing: progress information. That is, when sending a large file via HTTP, the users would need to know how much of the file was already sent and how much more still remains to be sent. Therefore, I extended Vlad’s class to provide upload progress information.

Background

To better understand the methodology of using this class and the ideas behind it, I suggest reading Vlad’s article about his class ClientHTTPRequest. You can find the article here.

Now I modified this class to provide for progress information by making the following changes:

  1. Defer making the HTTP connection until the actual posting takes place – the original class connects as soon as the write() function is called. In this version, the write function is called but no connection is made.
  2. All the write() calls cause the data to be written to a ByteArrayOutputStream, rather than directly to the OutputStream of the connection. This is done because the content-length is needed to know ahead of time (before actually streaming the data over through the socket) in order to provide for progress information and also in order to use the special setFixedLengthStreamingMode mode for the connection:
        …ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
        protected void write(char c) throws Exception {
            baos.write(c);
        }
        
        protected void write(String s) throws Exception {
            baos.write(s.getBytes());
        }
  3. When the post() is called, only then an HTTP connection is created. This connection is given the setFixedLengthStreamingMode setting. Then, the contents of baos (the ByteArrayOutputStream to which everything was written), gets piped into the HTTP connection output stream in increments of 50 KB at a time.
  4. It is also worthwhile to mention the addition of the SubmitProgress interface, which is used to make clients of this class able to receive the following progress call backs:
    public interface SubmitProgress {
        //called every 50KB of transfer to report how much was transferred so far
        public void bytesTransferred(long bytes); 
        //tells the client how many bytes will actually get transferred. 
        //Useful to set a progress bar’s top limit (setMaximum()).
        public void setBytesToTransfer(long bytes); 
        //provides the current status of the operation
        public void statusMessage(String status); 
        //called when the upload has been completed.
        public void transferComplete(); 
    }

Using the Code

To use this code, you will need to include ClientHTTPRequest2.java and SubmitProgress.java in your project. You will also need to implement the SubmitProgress interface in order to receive progress information about the upload. Notice that you can set HTTP parameters (ones that can later be retrieved by your servlet/cgi code as if a Web browser placed them in the URL query) and of course, you can also append an entire file to the request. For instance, the snippet below shows how you would submit a file and 2 parameters: user and password.

ClientHttpRequest2 chr=new ClientHttpRequest2(submitUrl);
//csp is an implementation of the SubmitProgress Interface. 
chr.setSubmitProgress(csp); 
chr.setParameter("user",user);
chr.setParameter("password",password);
chr.setParameter("filename",new File(filename));

The above code will send an HTTP request to the Web server pointed to by submitUrl. This request will have the parameters user, password and will also submit the contents of the file “filename” to the server. (Note: the server will need to know how to parse the multipart format of the data). Progress information will be provided through the SubmitProgress interface. For example, the method SubmitProgress.bytesTransferred(long bytes) will be called periodically to notify how many bytes were already transferred.

The demo (available for download with this article) performs a submit to a server at the localhost URL. You should change that URL to a webserver that is running remotely, and if the connection to it is say, DSL, which is relatively slow, you will get to see the upload progress. To run the demo, simply compile all the files (javac *.java) and run the Main.java file (java Main). Then on the frame that shows up, click "Choose File". You should choose a large file. Then, the button will change to "Upload File". Press that and the file + the two parameters will get uploaded. The class DemoFrame in this demo, is a good example of how to implement the SubmitProgress interface in order to get progress information.

History

  • 27th January, 2006: Version 1.0

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here