Using binary data with REST

Begin mea culpa. One of the features that Dave Carroll and I briefly mentioned during our Winter ’12 Preview webinar earlier today was the ability to insert and update binary data using the Force.com REST API. This is currently a Pilot feature in Winter ’12 (i.e. you’ll need to contact Salesforce support to have it enabled for you) that allows you to insert and update up to 500Mb of binary data into any Standard Object (e.g. Attachment, Document or ContentVersion) using the standard Force.com REST API. Previously, the REST API supported querying blob fields and inserting/updating Base64 encoded binary data (upto 50MB), but with this new Pilot feature the REST API now supports the MIME multipart content-type standard which allows you to upload large binary files of up to 500Mb (no additional encoding required).

But that’s not what this blog post is about. After the webinar, one of attendees – Richard Tuttle –  posted a very pertinent question on Twitter. To paraphrase Richard, apart from the standard Force.com REST API can I also process blob data via Apex REST (which is GA in Winter ’12 btw)? In my haste to answer, I tweeted back that Blob primitives are not supported as return or parameter types in Apex REST and so the answer is no. Wrong answer. I’ll conveniently blame it on my earlier that usual wakeup alarm (the first webinar was @ 7am PST), but the bottom-line is that I should have known better. In fact, I had even demoed processing blob/binary data in an Apex REST service in the webinar that Alex Toussaint and I did on the topic a couple of month back! What I had forgotten in my haste to reply to Richard was that even though you can’t use a Blob primitive as the return or parameter type for an Apex REST method, you can still use the standard RestRequest and RestResponse classes to access the request or response data as blob/binary.

Here’s a small snippet from the Apex REST class that I demoed during the Apex REST webinar.

@RestResource(urlMapping='/CaseManagement/v1/*')
global with sharing class CaseMgmtService
{
     .....
    @HttpPost
    global static String attachPic(RestRequest req, RestResponse res){
        Id caseId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        Blob pic = req.requestBody;
        Attachment a = new Attachment (ParentId = caseId,
                                       Body = pic,
                                       ContentType = 'image/jpg',
                                       Name = 'SendViaMyPhone');
        insert a;
        return a.Id;
    }
}

The method accepts a picture taken from an Android device and adds it as an Attachment to an existing Case record. Here’s the corresponding Java code snippet from my Android sample application that invokes the above Apex REST service.

String resourceURI = loginResult.getInstanceUrl() +
                          "/services/apexrest/CaseManagement/v1/"+sobjectId;
HttpClient client = AndroidHttpClient.newInstance("Android");
HttpPost getRequest = new HttpPost(resourceURI);
getRequest.setHeader("Authorization", "OAuth " + loginResult.getAccessToken());
getRequest.setHeader("Content-Type", "application/json");

getRequest.setEntity(new ByteArrayEntity(jpeg[0]));

try {
        HttpResponse response = client.execute(getRequest);
}catch (Exception e) {}

So, the bottom-line is that it’s absolutely possible to process binary data with Apex REST. You just have to use the RestRequest/RestResponse classes to work with the binary data instead of defining Blob return types or parameters in your Apex REST method. Sorry Richard – hopefully this detailed post makes up for misinforming you earlier. End mea culpa.

Published
September 28, 2011
Topics:

Leave your comments...

Using binary data with REST