Friday, 9 March 2012

Java Multipart Upload Code (Android Friendly)



This is a quick function to do a multipart upload of a file in android (and Java in general). It is adapted from Adrian Smith's code here: http://www.17od.com/2010/02/18/multipart-form-upload-on-android/.

 The differences are:
  1. This function will not try to read the file into a string (which imposes size restrictions).
  2. You can pass the content type of the file upon execution
  3. It returns whether or not it was successful and the HTTP response code.
  4. It does not read the response to the upload (if you want to add it back in, the code is in Adrian Smith's page above).

private NetworkResult sendFileMultipart(String targetURL, File file, String contentType, String field, String username, String password) {
  StringBuffer requestHeader = new StringBuffer();
  StringBuffer requestFooter = new StringBuffer();
  NetworkResult result = new NetworkResult();
  
  String BOUNDARY = "==================================";
  HttpURLConnection conn = null;
  byte[] buf = new byte[1024];
  int responseCode = -1; // Keeps track of any response codes we might get.
  
  result.setResponseCode(responseCode);
  result.setIsSuccesfull(false);
  
  try {
   // These strings are sent in the request body. They provide information about the file being uploaded
   String contentDisposition = "Content-Disposition: form-data; name=\""+field+"\"; filename=\"" + file.getName() + "\"";
   String contentType = "Content-Type: " + contentType;

   // This is the standard format for a multipart request header
   requestHeader.append("--");
   requestHeader.append(BOUNDARY);
   requestHeader.append('\n');
   requestHeader.append(contentDisposition);
   requestHeader.append('\n');
   requestHeader.append(contentType);
   requestHeader.append('\n');
   requestHeader.append('\n');

   // This is the standard format for a multipart request footer
   requestFooter.append('\n');
   requestFooter.append("--");
   requestFooter.append(BOUNDARY);
   requestFooter.append("--");

   // Read the file
   FileInputStream fis = new FileInputStream(file);

   // Make a connect to the server
   URL url = new URL(targetURL);
   conn = (HttpURLConnection) url.openConnection();

   // Put the authentication details in the request (if needed)
   if (username != null) {
    String usernamePassword = username + ":" + password;
    String encodedUsernamePassword = Base64.encodeBytes(usernamePassword.getBytes());
    conn.setRequestProperty ("Authorization", "Basic " + encodedUsernamePassword);
   }

   conn.setDoOutput(true);
   conn.setDoInput(true);
   conn.setUseCaches(false);
   conn.setRequestMethod("POST");
   conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

   // Send the body
   DataOutputStream dataOS = new DataOutputStream(conn.getOutputStream());
   dataOS.writeBytes(requestHeader.toString());

   try {
    for (int readNum; (readNum = fis.read(buf)) != -1;) {
     dataOS.write(buf, 0, readNum); //no doubt here is 0
    }
   } catch (IOException ex) {
    throw new Exception(String.format("Error reading file!"));
   }

   dataOS.writeBytes(requestFooter.toString());
   dataOS.flush();
   dataOS.close();

   // Ensure we got the HTTP 200 response code
   responseCode = conn.getResponseCode();
   result.setResponseCode(responseCode);

   if (responseCode != 200) {
    result.setIsSuccesfull(false);
    throw new Exception(String.format("Received the response code %d from the URL %s", responseCode, url));
   } else {
    result.setIsSuccesfull(true);
   }
  }catch (Exception e){
   
   // I am not interested on exactly why this failed, only that it has.
   // This can be extended by specific Exception handling.
   
   result.setResponseCode(responseCode); // try to salvage the response code.. probably -1 at this point.
  } finally {
   if (conn != null) {
    conn.disconnect();
   }
  }

  return result;
 }

Notes:
  • NetworkResult is a simple POJO which stores an int (responseCode) and a boolean (isSuccessful) for handling on the other side.
  • You might want to test for the file's existence before you call this function.
  • This will only upload a single file, but it should be fairly easy to extend it to to upload more by iterating though a list. (if you do that and it fails, make sure you have line breaks where you must.)

5 comments:

  1. It is really very good post Java Multipart Upload Code...


    thanks to share...

    ReplyDelete
  2. What will be the Content Type we need to send as a parameter??

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. how to transfer parameter with file without pass para. in url ??

    ReplyDelete