Resumable upload from Java client to Grails web application?

Posted by dersteps on Stack Overflow See other posts from Stack Overflow or by dersteps
Published on 2012-07-06T15:12:54Z Indexed on 2012/07/06 15:15 UTC
Read the original article Hit count: 197

Filed under:
|
|
|
|

After almost 2 workdays of Googling and trying several different possibilities I found throughout the web, I'm asking this question here, hoping that I might finally get an answer.

First of all, here's what I want to do:

I'm developing a client and a server application with the purpose of exchanging a lot of large files between multiple clients on a single server. The client is developed in pure Java (JDK 1.6), while the web application is done in Grails (2.0.0).

As the purpose of the client is to allow users to exchange a lot of large files (usually about 2GB each), I have to implement it in a way, so that the uploads are resumable, i.e. the users are able to stop and resume uploads at any time.

Here's what I did so far:

I actually managed to do what I wanted to do and stream large files to the server while still being able to pause and resume uploads using raw sockets. I would send a regular request to the server (using Apache's HttpClient library) to get the server to send me a port that was free for me to use, then open a ServerSocket on the server and connect to that particular socket from the client.

Here's the problem with that:

Actually, there are at least two problems with that:

  1. I open those ports myself, so I have to manage open and used ports myself. This is quite error-prone.
  2. I actually circumvent Grails' ability to manage a huge amount of (concurrent) connections.

Finally, here's what I'm supposed to do now and the problem:

As the problems I mentioned above are unacceptable, I am now supposed to use Java's URLConnection/HttpURLConnection classes, while still sticking to Grails.

Connecting to the server and sending simple requests is no problem at all, everything worked fine. The problems started when I tried to use the streams (the connection's OutputStream in the client and the request's InputStream in the server). Opening the client's OutputStream and writing data to it is as easy as it gets. But reading from the request's InputStream seems impossible to me, as that stream is always empty, as it seems.

Example Code

Here's an example of the server side (Groovy controller):

def test() {
    InputStream inStream = request.inputStream

    if(inStream != null) {
        int read = 0;
        byte[] buffer = new byte[4096];
        long total = 0;

        println "Start reading"

        while((read = inStream.read(buffer)) != -1) {
            println "Read " + read + " bytes from input stream buffer"      //<-- this is NEVER called
        }       

        println "Reading finished"
        println "Read a total of " + total + " bytes"   // <-- 'total' will always be 0 (zero)
    } else {
        println "Input Stream is null"      // <-- This is NEVER called
    }
}

This is what I did on the client side (Java class):

public void connect() {
    final URL url = new URL("myserveraddress");
    final byte[] message = "someMessage".getBytes();        // Any byte[] - will be a file one day
    HttpURLConnection connection = url.openConnection();
    connection.setRequestMethod("GET");                     // other methods - same result

    // Write message 
    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
    out.writeBytes(message);
    out.flush();
    out.close();

    // Actually connect
    connection.connect();                                   // is this placed correctly?

    // Get response
    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

    String line = null;
    while((line = in.readLine()) != null) {
        System.out.println(line);                   // Prints the whole server response as expected
    }

    in.close();
}

As I mentioned, the problem is that request.inputStream always yields an empty InputStream, so I am never able to read anything from it (of course). But as that is exactly what I'm trying to do (so I can stream the file to be uploaded to the server, read from the InputStream and save it to a file), this is rather disappointing.

I tried different HTTP methods, different data payloads, and also rearranged the code over and over again, but did not seem to be able to solve the problem.

What I hope to find

I hope to find a solution to my problem, of course. Anything is highly appreciated: hints, code snippets, library suggestions and so on. Maybe I'm even having it all wrong and need to go in a totally different direction.

So, how can I implement resumable file uploads for rather large (binary) files from a Java client to a Grails web application without manually opening ports on the server side?

© Stack Overflow or respective owner

Related posts about java

Related posts about grails