Link to home
Start Free TrialLog in
Avatar of javaq092999
javaq092999

asked on

Posting a document using HttpURLConnection?

My Platform : JDK1.4/Windows2000

I have an HTTP server running. A program (addFile) in it allow users to upload a file. The code is like this (it works just fine)...

    <form action="addFile" method="post" enctype="multipart/form-data">
    <input type="file" name="file"><br>
    <input type="submit" value=" Upload File ">
    </form>


I need to replicate the same thing from a Java program (Swing). For this I am using the HttpURLConnection abstract class. Getting a document is not a problem but posting a document is. I am trying following code but it is not working. What is wrong here...


import java.io.*;
import java.net.*;

public class PostDocument {
    public static void main(String[] args) throws Exception {
        String url = "http://localhost:8080/Examples/FileLibrary/addFile";
        String docPath = "D:\\rcn\\java\\HttpURLConnection\\testdoc.xml";    // Document

        HttpURLConnection httpcon = (HttpURLConnection) ((new URL(url).openConnection()));
        httpcon.setDoOutput(true);
        httpcon.setUseCaches(false);
        httpcon.setRequestProperty("Content-Type", "multipart/form-data");
        httpcon.connect();

        System.out.println("Posting " +docPath +"...");
        File file = new File(docPath);
        FileInputStream is = new FileInputStream(file);
        OutputStream os = httpcon.getOutputStream();

        // POST
        // Read bytes until EOF to write
        byte[] buffer = new byte[4096];
        int bytes_read;    // How many bytes in buffer
        while((bytes_read = is.read(buffer)) != -1) {
            os.write(buffer, 0, bytes_read);
        }
        os.close();
        is.close();

        System.out.println("Done...");
    }
}
Avatar of bobbit31
bobbit31
Flag of United States of America image

have you tried:
httpcon.setRequestMethod("POST")

You need that. The default request method is GET, which  has an upper bound on the amount of data it can transmit.
Avatar of Mick Barry
Your request needs to be formatted specifically for a multipart/form-data, you can't just send the file.
Avatar of heinousjay
heinousjay

check out http://jakarta.apache.org/commons/ for the HttpClient.  I don't know if it handles multipart requests yet, but it probably wouldn't hurt to look.
Avatar of javaq092999

ASKER

-- objects,

I tried wrapping the content of my text file as described in RFC1867, but could not succeed. I am sure I am doing something wrong. Could you please provide some pointer/link for a valid example/article.

Here is the code snippet I tried...
....
       String req = //"Content-type: multipart/form-data, boundary=AaB03x\r\n\r\n"
                     "\r\n--AaB03x\r\n"
                     +"content-disposition: form-data; name=\"file\"; filename=\"testdoc.xml\"\r\n"
                     +"Content-Type: text/plain\r\n\r\n"
                     +"<Hello>Hello There</Hello>\r\n"
                     +"--AaB03x--\r\n";

        DataOutputStream os = new DataOutputStream(httpcon.getOutputStream());
        os.writeBytes(req);
        os.flush();
....

-- heinousjay,

HttpClient doesn't seems to have the support yet for the multipart.
     String req = "Content-type: multipart/form-data, boundary=AaB03x\r\n\r\n"
                    +"--AaB03x\r\n"
                    +"content-disposition: form-data; name=\"file\"; filename=\"testdoc.xml\"\r\n"
                    +"Content-Type: text/plain\r\n\r\n"
                    +"<Hello>Hello There</Hello>\r\n"
                    +"--AaB03x--\r\n";
-----------------------------------------------------------
      String req = //"Content-type: multipart/form-data, boundary=AaB03x\r\n\r\n"
                    "\r\n--AaB03x\r\n"
                    +"content-disposition: form-data; name=\"file\"; filename=\"testdoc.xml\"\r\n"
                    +"Content-Type: text/plain\r\n\r\n"
                    +"<Hello>Hello There</Hello>\r\n"
                    +"--AaB03x--\r\n";
should be something like this:
...
httpcon.setRequestProperty("Content-Type", "multipart/form-data, boundary=AaB03x"); // this is new line
httpcon.connect();

System.out.println("Posting " +docPath +"...");
File file = new File(docPath);
FileInputStream is = new FileInputStream(file);
OutputStream os = httpcon.getOutputStream();
// this is new line
os.write("content-disposition: form-data; name=\"file\"; filename=\"testdoc.xml\"\r\nContent-Type: text/plain\r\n\r\n".getBytes());
();
// POST
// Read bytes until EOF to write
byte[] buffer = new byte[4096];
int bytes_read;    // How many bytes in buffer
while((bytes_read = is.read(buffer)) != -1) {
  os.write(buffer, 0, bytes_read);
}
os.write("--AaB03x".getBytes()); // another 2 new lines
os.flush(); //
os.close();
is.close();

System.out.println("Done...");
                         
Hi,

just a little addition Venc75's solution. Be sure to prepend a "\r\n" before writing the boundary after the file, this is part of the spec. The 2nd boundary must look like this.

os.write("\r\n--AaB03x".getBytes());

bye, x4u.
I've found server can be extremely fussy about multipart form posts, on character wrong and the whole thing fails.

Try http://www.innovation.ch/java/HTTPClient/, I believe it supports multipart posts.
x4u,
====

os.write("\r\n--AaB03x".getBytes());
 should be
os.write("\r\n--AaB03x--".getBytes());

objects,
========

Did not find any multipart specific API there!

All,
====

I could run my *JAVA HTTP Client program* successfully using Tomcat4.0.3 and a URL Upload.jsp (that uses com.orelly.servlet.MultiPart). But I am also trying another server called "Zope" the same program gives me a 500 error. I am posting the error message below if you can give some clue...


null: HTTP/1.1 500 Internal Server Error
Server: Zope/(Zope 2.5.1 (binary release, python 2.1, win32-x86), python 2.1.3, win32) ZServer/1.1b1
Date: Thu, 10 Oct 2002 12:57:34 GMT
Bobo-Exception-File: C:\Zope\bin\lib\cgi.py
Content-Type: text/html
Bobo-Exception-Type: ValueError
Bobo-Exception-Value: bobo exception
Etag:
Content-Length: 1704
Bobo-Exception-Line: 603

getRequestMethod   : POST
getResponseCode    : 500
getResponseMessage : Internal Server Error


---------------------------------------------------------
Here is my entire working program
---------------------------------------------------------
import java.io.*;
import java.net.*;

/**
 *    RFC 1867
 *    ========
 *        Content-type: multipart/form-data, boundary=AaB03x
 *
 *        --AaB03x
 *        content-disposition: form-data; name="field1"
 *
 *        Joe Blow
 *        --AaB03x
 *        content-disposition: form-data; name="pics"; filename="file1.txt"
 *        Content-Type: text/plain
 *
 *         ... contents of file1.txt ...
 *        --AaB03x--
 */
public class PostDocument {
    public static void main(String[] args) throws Exception {
        //
        // CONSTANTS
        //
        String url = "http://localhost:8080/Examples/FileLibrary/addFile";   // <--- Zope/Python
        // String url = "http://localhost:8080/rcn/jsp/UploadFile.jsp?action=upload"; // <--- Tomcat/JSP
        String docPath = "D:\\rcn\\java\\HttpURLConnection\\testdoc.txt";
        String bndry = "AaB03x";
        String paramName = "file";
        String fileName = "testdoc.txt";

        //
        // CREATE AN HTTP CONNECTION
        //
        HttpURLConnection httpcon = (HttpURLConnection) ((new URL(url).openConnection()));
        httpcon.setDoOutput(true);
        httpcon.setUseCaches(false); // ??? Not Required?
        httpcon.setRequestMethod("POST");
        httpcon.setRequestProperty("Content-type", "multipart/form-data, boundary=" +bndry); // this is new line
        httpcon.connect();

        //
        // OPEN THE READ AND WRITE STREAMS
        //
        System.out.println("Posting " +docPath +"...");
        File file = new File(docPath);
        FileInputStream is = new FileInputStream(file);
        OutputStream os = httpcon.getOutputStream();

        //
        // WRITE THE FIRST/START BOUNDARY
        //
        String disptn = "--" +bndry +"\r\ncontent-disposition: form-data; name=\"" +paramName +"\"; filename=\"" +fileName +"\"\r\nContent-Type: text/plain\r\n\r\n";
        System.out.print(disptn);
        os.write(disptn.getBytes());

        //
        // WRITE THE FILE CONTENT
        //
        byte[] buffer = new byte[4096];
        int bytes_read;
        while((bytes_read = is.read(buffer)) != -1) {
            os.write(buffer, 0, bytes_read);
            System.out.print(new String(buffer, 0, bytes_read));
        }

        //
        // WRITE THE CLOSING BOUNDARY
        //
        String boundar = "\r\n--" +bndry +"--";
        System.out.print(boundar);
        os.write(boundar.getBytes()); // another 2 new lines

        //
        // FLUSH / CLOSE THE STREAMS
        //
        os.flush();
        os.close();
        is.close();

        // DEBUG
        System.out.println("\n....Done!!!...\n\n");
        dump(httpcon);
    }

    public static void dump(HttpURLConnection httpcon) throws IOException {
        int n=0; // n=0 has no key, and the HTTP return status in the value field
        String headerKey;
        String headerVal;

        while (true){
            headerKey = httpcon.getHeaderFieldKey(n);
            headerVal = httpcon.getHeaderField(n);

            if (headerKey != null || headerVal != null) {
                System.out.println(headerKey +": " +headerVal);        
            }
            else {
                break;
            }

            n++;
        }

        System.out.println();
        System.out.println("getRequestMethod   : " +httpcon.getRequestMethod());
        System.out.println("getResponseCode    : " +httpcon.getResponseCode());
        System.out.println("getResponseMessage : " +httpcon.getResponseMessage());
    }
}


ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial