7

We are integrating an IOS app with salesforce and need to upload image data by apex rest class. we packed image base64 data and other data into JSON string, then send it. Now we get the JSON data in apex class but have no idea how to save the base64 image data as salesforce attachment.

This is Json data sample:

{
  "records" : [
    {
      "records" : "Image Base64 Data"
    },
    {
      "records" : "Image Base64 Data"
    }
  ]
}

This is apex rest class,

@RestResource(urlMapping='/MyWebService/*')
global class MyWebService 
{
    @HttpPost
    global static void receiveData(String a)
    {  
        String jsonStr = EncodingUtil.base64Decode(a).toString();
        JSONParser parser = JSON.createParser(jsonStr);
        while (parser.nextToken() != null) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME){
                String fieldName = parser.getText();
            }
            if (parser.getCurrentToken() == JSONToken.VALUE_STRING){
                Attachment attach = new Attachment();
                **attach.Body = parser.getBlobValue();**
                attach.Name='Test';
                attach.ContentType='image/jpg';
                attach.ParentId='0019000000v8W34';
                insert attach;
            }
        }
    }
}

As a result, we can't save image base64 data as attachment body. We checked logs, got StringException error and totally have no idea what happened. Did anyone got this and how to solve it? Thanks in advance.

4 Answers 4

7

You can do it like this:

jsonStr = EncodingUtil.base64Decode(jsonData).toString();
List<Attachment> attaches = new List<Attachment>();
for(Records record : parse(jsonStr).records)
{
     attaches.addAll(buildAttachment(record));
}
insert attaches;

global static List<Attachment> buildAttachment(Records data)
{
    List<Attachment> attaches = new List<Attachment>();
    if(data.name == 'SFA_Photo')
    {
        for(String str : data.values)
        {
            String[] dataList = str.split('\\|');
            if(dataList[1].startsWith('001'))
            {
                Attachment attach = new Attachment();
                attach.contentType = 'image/jpg';
                attach.name = dataList[0];
                attach.parentId = dataList[1];
                attach.body = EncodingUtil.base64Decode(dataList[2]);
                attaches.add(attach);   
            }
        }
    }
    return attaches;
}
1
  • Yue, how can i pass parameters with attachment through postman? Can you please share me parameters and attachment structure? Feb 26, 2020 at 6:06
5
@RestResource(urlMapping='/MyWebService/*')
global class MyWebService 
   {
@HttpPost
global static void receiveData(String a)
{  
    Blob blbdata = EncodingUtil.base64Decode(a);//Keep it in blob itself .Dont convert to string again 
    JSONParser parser = JSON.createParser(jsonStr);
    while (parser.nextToken() != null) {
        if (parser.getCurrentToken() == JSONToken.FIELD_NAME){
            String fieldName = parser.getText();
        }
        if (parser.getCurrentToken() == JSONToken.VALUE_STRING){
            Attachment attach = new Attachment();
            attach.Body = blbdata;//Populate blob data 
            attach.Name='Test';
            attach.ContentType='image/jpg';
            attach.ParentId='0019000000v8W34';
            insert attach;//Collect in List and then do an insert in bulk to avoid governor limit
        }
     }
   }

 }

COrrected the code .You will just need to do a base64 decode and insert in attachment body as shown above

5

The platform can convert JSON into simple Apex classes for you.

Usually you can just include the root object in the @HttpPost method signature, but Blob is not supported in that context. So for data including Blob fields you need to use this pattern:

@RestResource(urlMapping='/MyWebService/*')
global class MyWebService {
    @TestVisible private static Id PARENT_ID = '0019000000v8W34';
    private class Data {
        Record[] records;
    }
    private class Record {
        Blob records;
    }
    @HttpPost
    global static void receiveData() {
        Data d = (Data) JSON.deserialize(
                RestContext.request.requestBody.toString(),
                Data.class
                );
        Attachment[] attachments = new Attachment[] {};
        for (Record r : d.records) {
            attachments.add(new Attachment(
                    Name = 'Test',
                    Body = r.records,
                    ContentType='image/jpg',
                    ParentId = PARENT_ID
                    ));
        }
        insert attachments;
    }
}

Here is the test case:

@isTest
private class MyWebServiceTest {
    @isTest
    static void test() {
        Account parent = new Account(Name = 'Acme');
        insert parent;
        MyWebService.PARENT_ID = parent.Id;

        // 93 byte PNG image base64 encoded
        String jsonString = '{"records":[{"records":"iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEWxf2/KgHhvwEfedoetG6yMAAAADElEQVQI12NoYCgAAAH0APFbzVilAAAAAElFTkSuQmCC"}]}';
        RestRequest request = new RestRequest();
        request.requestBody = Blob.valueOf(jsonString);
        RestContext.request = request;

        MyWebService.receiveData();

        System.assertEquals(1, [select count() from Attachment]);
        System.assertEquals(93, [select BodyLength from Attachment].BodyLength);
    }
}
2

Try to do something like this:

attach.Body = EncodingUtil.base64Decode(parser.getBlobValue().replace('data:image/png;base64,', ''));

Also you should try to use the Salesforce standard Json.deserialize method. ;-)

1
  • This code couldn't work because the blob type don't have 'replace' method. Maybe you missed something in your code. Please check.
    – Allen Li
    May 25, 2014 at 8:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .