Performing a Form File Upload using BlackBerry Dynamics APIs

Jump straight to the sample on Github here:  GDHttpClientFileUpload Sample

The BlackBerry Dynamics SDK includes APIs that allow for secure network communication between an app and a server located within your corporate network.  If you are not yet familiar on how that works take a look at our getting started guide for an architectural overview.

In this article I’m going to explain how you can use these APIs to upload a file using HTML Forms based submission.

The first thing you'll need is a web server ready to accept your file upload.  Since you’re reading this, you likely have one set up that you want to use.  But if not, the free Post Test Sever can be used.  It’s an online service that allows you to make HTTP GET and POST requests, records the submitted data and allows you to view it afterwards.  This is what the sample project makes use of.

Next, you'll create some code that uses GDHttpClient to make an HTTP connection.  A boundary is used to separate the multiple parts of the form data.  The networking code looks like this:

//The boundary for our multipart form. This can be any unique ASCII value. public static final String BOUNDARY = "----123456789987654321"; GDHttpClient httpclient = new GDHttpClient(); HttpPost post = new HttpPost(urlString); UploadContentProducer contentProducer = new UploadContentProducer(); HttpEntity entity = new EntityTemplate( contentProducer ); post.addHeader( "Connection", "Keep-Alive" ); post.addHeader( "Content-Type", "multipart/form-data; boundary=" + BOUNDARY ); post.setEntity( entity ); ByteArrayOutputStream bos = new ByteArrayOutputStream(); entity.writeTo(bos); HttpResponse response = httpclient.execute(post); InputStream stream = response.getEntity().getContent();
The key element in the code above is the UploadContentProducer.  The UploadContentProducer takes care of adding the files that will be uploaded along with any other form elements that make up the form.  The UploadContentProducer code looks like this:

class UploadContentProducer implements ContentProducer { //The content of the file to be uploaded. Usually you would read this from the file system. //For simplicity, this sample uploads this file contents from memory. private static final String FILE_CONTENTS = "Hello File!"; //The file name. private static final String FILE_NAME = "myfile.txt"; //This is the name of the file parameter in the multipart form. private static final String FILE_PARAMETER = "file_form_name"; //The prefix for the boundary, this must be --. private static final String DELIMITER = "--"; public UploadContentProducer() {} @Override public void writeTo(OutputStream outputStream) throws IOException { outputStream.write(("Content-Type: multipart/form-data; boundary=" + MainActivity.BOUNDARY).getBytes()); outputStream.write(("\r\n\r\n").getBytes()); // add this line before inserting any content //Add the form parts required by your multiplart form. addFormPart( outputStream, "form_parameter_name", "Form Parameter Value" ); //Add the file as a binary. addFilePart(outputStream, FILE_PARAMETER, FILE_NAME, FILE_CONTENTS.getBytes()); //Add this line at the end of the request outputStream.write((DELIMITER + MainActivity.BOUNDARY + DELIMITER).getBytes()); outputStream.flush(); outputStream.close(); } public void addFormPart( OutputStream os, String paramName, String value ) throws IOException { os.write((DELIMITER + MainActivity.BOUNDARY + "\r\n").getBytes()); os.write(("Content-Disposition: form-data; name=\"" + paramName + "\"\r\n").getBytes()); os.write("Content-Type: text/plain\r\n".getBytes()); os.write(("\r\n" + value + "\r\n").getBytes()); } public void addFilePart(OutputStream os, String paramName, String fileName, byte[] data) throws IOException { os.write((DELIMITER + MainActivity.BOUNDARY + "\r\n").getBytes()); os.write(("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"\r\n").getBytes()); os.write(("Content-Type: application/octet-stream\r\n").getBytes()); os.write(("Content-Transfer-Encoding: binary\r\n").getBytes()); os.write("\r\n".getBytes()); os.write(data); os.write("\r\n".getBytes()); } }

For simplicity, the sample code uses the String in the FILE_CONTENTS variable as the content of the file that is uploaded.  In your application the file would likely reside on the file system of the device, so you’d need to swap that constant for the contents of your file.

The addFilePart method accepts the file name and file contents and adds that to the request.  The example stores the file contents in a byte array in RAM, which will work fine for small to medium sized files.  If you need to upload large files, a buffering solution should be implemented instead.

The addFormPart method accepts the parameter names and values for all non-file elements of your form.  Call this method to add each element.

Try the sample yourself to see it in action.  You can clone the project from Github here:  GDHttpClientFileUpload Sample

Mark Sohm

About Mark Sohm

Senior Technical Solutions Manager on the Solution Architects team.

Mark Sohm joined BlackBerry in 2003 and currently works as a Senior Technical Solutions Manager on the Solutions Architects team. Mark Sohm has been helping developers create applications using BlackBerry technologies for over 15 years, starting way back with the very first BlackBerry JDK on BlackBerry OS 3.6 through to BlackBerry 10 and now Android with BlackBerry Dynamics and Android Enterprise.