3

I've got a legacy application that writes to an OutputStream, and I'd like to have the contents of this stream uploaded as a file to a Servlet. I've tested the Servlet, which uses commons-fileupload, using JMeter and it works just fine.

I would use Apache HttpClient, but it requires a File rather than just an output stream. I can't write a file locally; if there was some in-memory implementation of File perhaps that might work?

I've tried using HttpURLConnection (below) but the server responds with "MalformedStreamException: Stream ended unexpectedly".

        URL url = new URL("http", "localhost", 8080, "/upload");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        String boundary = "---------------------------7d226f700d0";
        connection.setRequestProperty("Content-Disposition", "form-data; name=\"file\""); 
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary);
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestMethod("POST");   
        connection.setChunkedStreamingMode(0);
        connection.connect();           

        OutputStream out = connection.getOutputStream();
        byte[] boundaryBytes =("--" + boundary + "\r\n").getBytes();
        out.write(boundaryBytes);


        //App writes to outputstream here

        out.write("\r\n".getBytes());
        out.write(("--"+boundary+"--").getBytes());
        out.write("\r\n".getBytes());

        out.flush();
        out.close();
        connection.disconnect();
DeejUK
  • 12,891
  • 19
  • 89
  • 169
  • By definition, there is no in-memory implementation of File. You can, however, replicate the HttpClient method and pass your bytes or stream directly, as that API most likely loads the file's bytes via a stream. – FThompson Sep 27 '12 at 14:24

1 Answers1

1

The PostMethod allows you to set a RequestEntity, which is an interface which you can implement. you just need to implement the RequestEntity.writeRequest method appropriately.

Or, if you want HttpClient to handle the multi-part stuff for you, you could use MultipartRequestEntity with a custom Part.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • Excellent - looks like I could even just implement `PartSource`. The legacy app takes `OutputStream` as an argument, and then writes to it, so I'm in control of what `OutputStream` goes in there. I'm guessing I could use a `ByteArrayOutputStream`, have the legacy code write to that, generate the byte array, and then implement a `PartSource` that takes a byte array instead of a file, and then provides an `ByteArrayInputStream` from that? – DeejUK Sep 27 '12 at 14:47
  • @Deejay - you could do that, but it wouldn't scale very well if you have large streams. – jtahlborn Sep 27 '12 at 15:45