Sending Complex Data From Java to PHP via a POST Request

I recently had to transfer files as well as simple text parameters from a Java application to a PHP script. Hence, I wanted the files to be available in the global $_FILES array and the simple parameters in the global $_POST array. Unfortunately, the task is not as easy as it sounds. One has to use MIME multipart messages. And there is no native support for MIME multipart in Java. Of course there are libraries which add MIME multipart support, but if one does not want to use external librariers, here is the „hard“ way. We will produce a message like the following:

Content-Type: multipart/form-data; boundary="BOUNDARY"

--BOUNDARY
Content-Disposition: form-data; name="param"

123456
--BOUNDARY
Content-Disposition: form-data; name="test"; filename="test.zip"
Content-Type: application/zip

BINARY_DATA

--BOUNDARY--

After sending this message to a PHP script, the parameter „param“ with the value „123456“ will be available in the $_POST array and the file „test“ will be available in the $_FILES array. But how can I do that in Java? Here you go:

// open a connection to the site and
// prepare it for sending multipart data
URL url = new URL("http://www.test.com/myscript.php");
URLConnection con = url.openConnection();
// create a boundary - must not be contained in the content!
String boundary = (UUID.randomUUID().toString() + UUID.randomUUID()
    .toString()).substring(0, 65);
con.setRequestProperty("Content-Type", "multipart/form-data; "
    + "boundary=\"" + boundary + "\"");
con.setDoOutput(true);
con.setUseCaches(false);
// use a BufferedOutputStream for performance reasons
BufferedOutputStream bos =
    new BufferedOutputStream(con.getOutputStream());
// use a PrintStream to easily write strings to the output stream
PrintStream ps = new PrintStream(bos, false, "UTF-8");
ps.println("--" + boundary);
ps.println("Content-Disposition: form-data; name=\"param\"");
ps.println();
ps.println("123456");
// [...] send other parameters
ps.flush();
// send the file(s)
DataOutputStream dos = new DataOutputStream(ps);
ps.println("--" + boundary);
ps.println("Content-Disposition: form-data; "
    + "name=\"test\"; filename=\"test.zip\"");
ps.println("Content-Type: application/zip");
ps.println();
ps.flush();
String filename = "/home/simon/test.txt";
FileInputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[0xFFFF];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
    dos.write(buffer, 0, bytesRead);
}
dos.flush();
// close the multipart message
ps.println();
ps.println("--" + boundary + "--");
// this flushes and closes all streams
dos.close();

If you want to dig deeper into the MIME multipart protocol, have a look at RFC 1341 and the ones updating it.

If this article has helped or you have made your own experiences with sending text parameters as well as files via a POST request from Java, I am happy to read it in the comments!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert