Monday, March 05, 2012

Sending Multipart Form Data from Java (and receiving it via PHP)

If you want to send binary data and some parameters, you'll need to execute a POST with the content type of multipart/form-data. This takes a different format than usual HTTP requests. The secret to sending multipart form data is sending the right number of line endings. Rather than explain it, here's the code.
String lineEnd = "\r\n"; 
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
File temp_file = new File("foo.txt");
// open a URL connection
URL url = new URL(urlString);

// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();

// Allow Inputs
conn.setDoInput(true);

// Allow Outputs
conn.setDoOutput(true);

// Don't use a cached copy.
conn.setUseCaches(false);

// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);

dos = new DataOutputStream( conn.getOutputStream() );

// Send parameter #1
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"param1\"" + lineEnd + lineEnd);
dos.writeBytes("foo1" + lineEnd);

// Send parameter #2
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"param2\"" + lineEnd + lineEnd);
dos.writeBytes("foo2" + lineEnd);

// Send a binary file
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + temp_file.getName() +"\"" + lineEnd);
dos.writeBytes(lineEnd);

// create a buffer of maximum size

bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];

// read file and write it into form...

bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

// send multipart form data necesssary after file data...

dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

// close streams
fileInputStream.close();
dos.flush();
dos.close();


Ok, now how to read this on the other end? Here's how to do it via PHP:
// Make sure a binary file is attached to the POST
if(!$_FILES) {
echo "No file!"
}

$id = $_FILES['uploadedfile']['name'];
move_uploaded_file($_FILES['uploadedfile']['tmp_name'], "/permanent/location".$id);

// Uncomment next line to print out the array to a file
// file_put_contents("/permanent/location/".$id.".debug.txt", print_r($_POST, true));
$param1="";
$param2="";
if(isset($arguments['param1'])) {
$lat = $arguments['param1'];
}
if(isset($arguments['param2'])) {
$lon = $arguments['param2'];
}
echo "Uploaded " . $id . " with param1=" . $param1 . " and param2=" . $param2;

7 comments:

Unknown said...

this is the exact thig we were looking for. thanks. :)

Swathy Kishore said...

hi, I am not able to get the param 1. I have exactly used the same code. Can you please help me?

Swathy Kishore said...

can you tell me what is your param1 in the java/android code?

Peter V said...

It's just some additional data. In this case I used it to store lat and long for the attached image. But you could store whatever data you like.

Unknown said...

Thanks a lot...

Unknown said...

Man!!!!

It was a great help. Really appreciate it :)

Unknown said...

C for Cat
C for Cat
C for Cat
C for Cat
C for Cat
C for Cat

Labels

Blog Archive

Contributors