Issues to POST streamed data to a webservice

Recently I had quite some issues with sending data via POST to a webservice from an Android app.

Let me quickly set the stage: I needed to upload data to a webservice via HTTPS. This data were dynamically generated PDF files created in the app. Since the files can become potentially large, I wanted to make sure that data would be streamed byte-wise to the webservice. I already had Volley and were using the HurlStack (which uses HttpUrlConnection).

In order to up-stream data would one needs to explicitly call either setFixedLengthStreamingMode() or setChunkedStreamingMode() on the UrlConnection. Without that the data that will go up would actually be stored in memory first. As I didn't want to take the risk that 3MB (or more) big files could blow my app with an OutOfMemoryException (especially on low-end devices, which are always short on memory!), I needed to take the safe road.

Setting up the workflow in the applications architecture was done quickly. Add some callbacks for preparing the data, counting data length and finally streaming data with an OutputStream. Worked perfectly! The problems kicked in, as I started to actually send data. I tried with fixed-length and chunked streaming mode. For fixed-length streaming mode one needs to the length of the full request body that is about to be sent. Contrary to the chunked streaming, were the connection would buffer up a certain amount of data and send it in (you guessed it!) chunks.

Unfortunatelly, chunked streaming mode wasn't supported by the webservice, so I had no alternatives left but use the fixed-length mode. But this resulted in exceptions complaining that the connection "expected 0 bytes but got 1 byte". Though, I was pretty sure that the content length used wasn't 0. Also going plain HTTP without SSL wouldn't be a real solution, I hoped maybe it's just the SSL connection causing problems. But it wasn't.

After lots of fiddling around with parameters, stepping through code and reading hidden platform classes, I came to the conclusion: something must be wrong with the HTTP(S) stack implementation in Android.

What came first to mind was OkHttp: an HTTP client with up-to-date TLS, SNI and SPDY support. No hesitation: get the library and its dependency Okio and drop everything into the project. To fully integrate OkHttp I needed to tell Volley to not use the platform's implementations. All that's needed is a subclass of HurlStack:

Without changing anything else of my implementations, the fixed-length upload streaming suddenly worked (which I take as a proof that indeed something is wrong with the platform implementations).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.