I spent a whole day trying to figure out how to use http components to send a file from a java program mimicking a POST multipart/form-data form.
The problem was that while a common HTML form worked with no problems at all, the POST generated with http commons was always rejected by the server.
So, I decided to dump the HTTP requests sent by the browser and by http components, and here’s what I got.
Request generated from the browser
------WebKitFormBoundaryYuxYFZoJg4fx2Tfu Content-Disposition: form-data; name="filename"; filename="index.idx" Content-Type: application/octet-stream [file content] ------WebKitFormBoundaryYuxYFZoJg4fx2Tfu--
Request generated from http commons
--xFwQ1jzWbqQIKivTUrK68BurHld66kpMCz3Fv9P Content-Disposition: form-data; name="filename"; filename="index.idx" Content-Type: application/octet-stream Content-Transfer-Encoding: binary [file content]
--xFwQ1jzWbqQIKivTUrK68BurHld66kpMCz3Fv9P--
As you can see there’s a “Content-Transfer-Encoding: binary” header that is the one that caused the problem in the server. After a while I discover than when you create a new MultipartEntity, you can optionally specify a mode of operation. Currently supported modes are HttpMultipartMode.STRICT and HttpMultipartMode.BROWSER_COMPATIBLE. It’s not worth to mention that the default mode in STRICT, that maybe does not work with old or not fully standard web servers. If BROWSER_COMPATIBLE is specified instead, the data sent by http commons does not contain any Content-Transfer-Encoding header, and the delivery of the file terminates successfully.
Here’s the piece of code:
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);