1

I am trying to upload files using Java URL class and I have found a previous question on stack-overflow which explains very well about the details, so I try to follow it. And below is my code adopted from the sniplet given in the answer.

My problem is that if I don't make a call to one of connection.getResponseCode() or connection.getInputStream() or connection.getResponseMessage() or anything which is related to reponse from the server, the request will never be sent to server. Why do I need to do this? Or is there any way to write the data without getting the response?

P.S. I have developed a server-side uploading servlet which accepts multipart/form-data and save it to files using FileUpload. It is stable and definitely working without any problem so this is not where my problem is generated.

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.io.IOUtils;

public class URLUploader {

    public static void closeQuietly(Closeable... objs) {
        for (Closeable closeable : objs) {
            IOUtils.closeQuietly(closeable);
        }
    }

    public static void main(String[] args) throws IOException {
        File textFile = new File("D:\\file.zip");
        String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.

        HttpURLConnection connection = (HttpURLConnection) new URL("http://localhost:8080/upslet/upload").openConnection();
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        OutputStream output = connection.getOutputStream();

        PrintWriter writer = new PrintWriter(output, true);
        // Send text file.
        writer.println("--" + boundary);
        writer.println("Content-Disposition: form-data; name=\"file1\"; filename=\"" + textFile.getName() + "\"");
        writer.println("Content-Type: application/octet-stream");
        FileInputStream fin = new FileInputStream(textFile);
        writer.println();
        IOUtils.copy(fin, output);
        writer.println();
        // End of multipart/form-data.
        writer.println("--" + boundary + "--");
        output.flush();
        closeQuietly(fin, writer, output);
        // Above request will never be sent if .getInputStream() or .getResponseCode() or .getResponseMessage() does not get called.
        connection.getResponseCode();
    }
}
Community
  • 1
  • 1
gigadot
  • 8,743
  • 7
  • 33
  • 49

3 Answers3

1

HttpURLConnection has a bunch of setters that affect the request, so it needs to know when you're done building the request so that it can send it off. The way it does this is by waiting until you actually ask for something back from the request, like the InputStream. (This is arguably a design flaw.) This is also why the setters throw an IllegalStateException "if already connected" -- once you call a getter the connection is established and it's too late to call a setter.

You should be able to call getInputStream() and then just close() it without actually reading from it.

Laurence Gonsalves
  • 125,464
  • 31
  • 220
  • 273
0

Just call getResponseCode(). That will initiate the transfer. You have to do that anyway to make sure the request succeeded, or find out why it failed.

user207421
  • 289,834
  • 37
  • 266
  • 440
0

for those who are checking this snippet, there's a line I think is wrong:

OutputStream output = output = connection.getOutputStream();

check it out ;)
By the way, It's true you have to use getResponseCode() method in a try to handle the exception when you make the connection, that's good in that way you make sure that your connection is working properly.

oers
  • 17,419
  • 11
  • 64
  • 73
  • 1
    Thank you for picking that up. i have corrected it. However, it wasn't wrong in term of compilation failure. It is just duplicated. – gigadot Feb 08 '12 at 22:11