+ Start a Discussion
David SomekhDavid Somekh 

Attachment body question

Hi Apex experts,

Looking at Attachment declaration I noticed that Body field is of type Base64.

The Body is an encoded data of a file.

Now, How can I decode the Body data? So I'll get the original contents of the file (it may be in bytes because I can use convert).


Another question.

Lets' say that I have the files data. How can I pass its data to me WebService written in C#? (what kind of type shall I use?)


Thank you so much!




The Body field in Apex is of type Blob, basically a binary representation of data. In the WSDL (when using SOAP), the format of the file is in Base64, because XML is a textual, not binary, format.


To get the contents of the attachment's body in to a normal String object in Apex, use:




 As an example, assuming you had an attachment already loaded, you can do this:



String bodyContent = myAttachment.body.toString();

To get an attachment into a XML-usable format (encoded in Base64, such as for sending through SOAP), use:



EncodingUtil.base64Encode(Blob.valueOf(myBodyContent)); // myBodyContent is normal string representation, not base64

If you already have a Base64-encoded string, you can retrieve its content by first decoding it into a Blob:



String data = EncodingUtil.base64Decode(myEncodedString).toString(); // myEncodedString is base64

To determine the type of data you should use, generate a WSDL for your service and generate an Apex Class definition for the WSDL.




I haven't had a need to write such a web service yet, but I would imagine that it would require either a Blob value or a Base64 encoded string (use the base64Encode method above).



David SomekhDavid Somekh


I Will try it and tell you what Hapend.

Only  a remark : in the Apwx documentation is Body field of type Byte64

Attachment API: http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_attachment.htm

Mitesh SuraMitesh Sura
sfdcfox, thanks as usual. But below snippet throws an exception "BLOB is not a valid UTF-8 string "
StaticResource att = [select id, name, body, ContentType from StaticResource where name = 'pdf_file' LIMIT 1]; 
string data = att.body.toString();
I am trying to grab PDF from static resource and show that inside VF page rendered as PDF. Any thoughts? Thank you for your time.

J. Scott CromieJ. Scott Cromie
I am also trying to decode an attachment, but outside of SFDC (i.e. in a node.js app).  I use jsforce to get the attachment like so:

      var server = conn.instanceUrl;
      var resource = 'services/data/v37.0/sobjects/Attachment/' + req.query.attachId + '/Body';
      var resourceURL = server + resource;
      var options = { method: 'GET',
                      url: resourceURL,
                        'content-type': 'text/plain; charset==x-user-defined',
 //                       'accept-encoding': 'gzip',
                        authorization: 'Bearer \'' + conn.accessToken + '\''
      var attData = conn.request(options);
attData in this case gives me what looks like binary data (here's a snippet:

'\u0000\u0010JFIF\u0000\u0001\u0002\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0000C\u0000\u0005\u0003\u0004\u0004\u0004\u0003\u0005\u0004\u0004\u0004\u0005\u0005\u0005\u0006\u0007\f\b\u0007\u0007\u0007\u0007\u000f\n\u000b\t\f\u0011\u000f\u0012\u0012\u0011\u000f\u0011\u0010\u0013\u0016\u001c\u0017\u0013\u0014\u001a\u0015\u0010\u0011\u0018!\u0018\u001a\u001c\u001d\u001f\u001f\u001f\u0013\u0017"$"\u001e$\u001c\u001e\u001f\u001e\u0000C\u0001\u0005\u0005\u0005\u0007\u0006\u0007\u000e\b\b\u000e\u001e\u0014\u0011\u0014\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u001e\u0000\u0011\b\u0000\u0000\u0003\u0001"\u0000\u0002\u0011\u0001\u0003\u0011\u0001\u0000\u001f\u0000\u0000\u0001\u0005\u0001\u0001\u0001\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\u0000\u0010\u0000\u0002\u0001\u0003\u0003\u0002\u0004\u0003\u0005\u0005\u0004\u0004\u0000\u0000\u0001}\u0001\u0002\u0003\u0000\u0004\u0011\u0005\u0012!1A\u0006\u0013Qa\u0007"q\u00142\b#B\u0015R$3br\t\n\u0016\u0017\u0018\u0019\u001a%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\u0000\u001f\u0001\u0000\u0003\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\u0000\u0011\u0000\u0002\u0001\u0002\u0004\u0004\u0003\u0004\u0007\u0005\u0004\u0004\u0000\u0001\u0002w\u0000\u0001\u0002\u0003\u0011\u0004\u0005!1\u0006\u0012AQ\u0007aq\u0013"2\b\u0014B\t#3R\u0015br\n\u0016$4%\u0017\u0018\u0019\u001a&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\u0000\f\u0003\u0001\u0000\u0002\u0011\u0003\u0011\u0000?\u0000\'Y\\j\u0002v\u0001\u0011\u0004`ri[)\u0017֭\bzVSAN_C\u0011\u0014\\c5\rɽO%XVB?\f`u}Xټɕa#(\u0011l \u00115=\u0014ŏ=&~\u001aӥh58V\nPɒ\u000f|Ś݄nv.=0\u0000>g1,[ߟt,:KS7&h.hp=+mTV\u0019Q\u0000\u001at-pf\u000b$[x7s^==I\u0014\u0004\u001d]ZaqCЌv#J\u0002ϡ\u0015G=o&`(p\u0006z"]\u000b\u0007\u0016Cjvf<o\bܮzdW\u0013gv`U-ͺPL\u00190\fF3:%QGSG)0VO\u0012ho\u00154qŝʶyֽO\u0019J(\u00013\u001cF[,:.....

, but I can't find in the docs where it says specifically what kind of encoding it uses (which would be helpful to decode it.).  Any ideas on how to turn this into usable data?  I eventually just want to return this out as a response to the end user.


Suyash SinghalSuyash Singhal

I am getting the same type of pdf content from 3rd party API. And I have to insert that PDF into Attachment under Account object.

I tried to convert this into blob - blob.valueOf(string) - string is the PDF content string that I am getting from API. And insert the attachment. The inserted PDF is empty and there is no content there. So I guess there is some issue with my parsing technique. Could you please let me know how did you parse this PDF content string to insert Attachment with proper content.????
J. Scott CromieJ. Scott Cromie
Hi Suyash - here's the code I'm using to bring the data into SFDC:

First - however you implement the control to select the file data, you'll have something similar to this:

      reader.onloadend = function(event) {
        var fileBlobControl = $("#fileBlobControl" + sfdcId);  //define the control that will hold the BLOB data
        var theResult = event.target.result; // get the file handle
        fileBlobControl.hide();  //ensure the control is hidden when the file comes in.
        var fileContents = new Uint8Array(theResult);// Use the Uint8Array format to get the file contents
        fileBlobControl[0].innerText = fileContents; // store the contents in the control.
Once you've implemented the UI piece, you'll need to prepare the BLOB for upload.

 // Create attachment object with required fields
    var att = new sforce.SObject("Attachment");
    att.Name = //Name of the file record;
    att.ContentType = //MIME type for the file;
    att.ParentId = //Whatever record you need to attach it to;
    att.Description = //The description ;
    att.IsPrivate = //boolean to describe if you need the record private or not.;

    // Populate attachment body
    var binary = "";
    var bytes = theFile.fileBlob.split(',');    //get the BLOB data here.  fileBlob is literally the file as uploaded from the browser control.
    var length = bytes.length;

*********  THIS IS KEY *********
**  You need to convert it from a
**  BLOB to a string of binary characters
**  prior to uploading it to SFDC

    for (var j = 0; j < length; j++) {
      binary += String.fromCharCode(bytes[j]);

    att.body = (new sforce.Base64Binary(binary)).toString();

    //Insert attachment
    sforce.connection.create([att], {
      onSuccess : function(result, source) {
     // Do something on success
      onFailure: function(error, source) {
      // Error handling

This works great for me.  It wasn't clear at first about how the binary string was supposed to be constructed, but it makes much more sense to me now.  And yes, unless there's another way that I haven't seen yet, you do have to convert character by character from the string array.

Let me know how it turns out for you.