8

I have a Rich Text Area field named 'test__c' that belongs to Case object. Is there any way to get images in that text area from apex code as Blob?

5

As of Spring '17 release, I could not get Keith's solution to work for me by making Http Callouts. Yes, the callout occurred, but the data I got back after following the 302 redirect sent back a web page wanting me to log in. Even after trying to set the request's Authorization header as discussed in the comments, no luck for me.

However, I did find similar question asked and their solution of using PageReference hitting the URL then using Blob b = page.getContent() method did get me the Blob as desired.

Get Rich Text Image URLs and Blob Data

My first step was to parse all of the <img> tags out of the rich text field so I knew the URLs. This question and solution inspired my logic:

// use reluctant regex to match each image tag individually
// https://docs.oracle.com/javase/tutorial/essential/regex/quant.html
Matcher imgMatcher = Pattern.compile( '<img(.+?)>' ).matcher( record.richTextField__c );

// iterate each image tag found
while ( imgMatcher.find() ) {

    // get the image tag html
    String imageTag = imgMatcher.group();
    System.debug( 'imageTag=' + imageTag );

    // get the value of the src attribute
    // the leading space is significant to avoid other attributes like data-cke-saved-src
    String imageURL = imageTag.substringBetween( ' src="', '"' );
    System.debug( 'imageURL=' + imageURL );

    // if url contained parameters they might be html escaped, unescape them
    // or, more conservatively, replace '&amp;' with '&'
    String decodedURL = imageURL.unescapeHtml4();
    System.debug( 'decodedURL=' + decodedURL );

    // note, as of API 34.0 or later, getContent() is considered an http callout
    // so take that into consideration for your unit tests and governor limits
    // https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/apex_System_PageReference_getContent.htm
    PageReference page = new PageReference( decodedURL );
    Blob b = page.getContent();
    System.debug( 'blob=' + b );

    System.debug( 'Enjoy your Blob, save it as a Document, ContentVersion, whatever!' );

    System.debug(''); // I like blank lines in my logs, easier to scan/read =)

}
3
  • hey @Doug, how did you determine content type of the embedded images? i tried page.getHeaders() but it's empty
    – hlopetz
    Jun 4 at 13:12
  • Inferred from the file extension. My use case was to stow them as ContentVersion records and it automatically sets the FileType field based on file extension. And if there was no file extension then I probably didn’t worry about the specific file type in my use case.
    – Doug Ayers
    Jun 5 at 18:42
  • lucky you. in my case there is no extension and i need the Content-Type header to correctly pass the image via base64-encoded string.
    – hlopetz
    Jun 7 at 17:10
4

You can with quite a lot of work.

First you will need to parse the text to find the <img> elements and in particular the src attribute of those. (Use e.g. the DOM classes.)

Then use some code that looks like this for each src attribute (I've hard coded and truncated one here):

// This location is an example from my org; will need to be different for your org
String location = 'https://c.na15.content.force.com/servlet/rtaImage?eid=500...';
do {
    HttpRequest req = new HttpRequest();
    req.setEndpoint(location);
    req.setMethod('GET');
    HttpResponse res = new Http().send(req);
    if (res.getStatusCode() == 302) {
        location = res.getHeader('Location');
    } else if (res.getStatusCode() == 200) {
        location = null;
        Blob b = res.getBodyAsBlob();
        // Return the Blob
    } else {
        // Error
    }
} while (location != null);

You will also have to add your equivalent of https://c.na15.content.force.com to the "Remote Site Settings" to allow the HTTP call to be made.

5
  • 1
    I used this code to get image but it in response it is login page body. I tried to 'Authorization : OAuth: <SessionID>' header for response. But it is not working from Salesforce side. Works only from browser side
    – pklochkov
    Sep 9 '15 at 14:52
  • @pklochkov I ran the Apex code using "Execute Anonymous". I don't know why req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId()); doesn't work.
    – Keith C
    Sep 9 '15 at 15:48
  • I think that this is because ap2.salesforce.com sessionId is used to authenticate to c.na15.content.force.com server. But when request performed from browser REST util it is OK.
    – pklochkov
    Sep 10 '15 at 7:23
  • @pklochkov The location value in the code I posted is an example: you will have to take a value from one of your text areas that include an image. You can do that initially by listing the field in the Developer Console. Your link will be different and should include "ap2" somewhere in it.
    – Keith C
    Sep 10 '15 at 7:35
  • 1
    Yes I know. I took that value directly from RTA on my org. So the result still the same
    – pklochkov
    Sep 10 '15 at 7:54
0

//manju

PageReference abc1 = new PageReference('Image url remove &amp in url'); string enco1 = EncodingUtil.base64Encode(abc1.getContent());
object.RTF__C= '<img alt="User-added image" src="data:image/jpeg;base64,'+ enco1+ '"></img>';

//" src="data:image/;base64, "> Refer this link http://developer.force.com/cookbook/recipe/converting-a-rich-text-area-fields-image-for-api-upload

0

sorry for necroposting. but that may be useful for someone like me who need both embedded image content and its meta-data.

in my case i have image URLs like the following https://instance.documentforce.com/servlet/rtaImage?eid=a3U7X000000XLRs&feoid=00N1L00000FLDsE&refid=0EM7X0000009FIf

here eid is record Id and refid is image one. with help of REST API guide i modified @Keith's answer and made the following code convert images to base64-encoded format to later pass them to 3rd-party APIs:

String location = 'https://instance.lightning.force.com/services/data/v52.0/sobjects/Custom_Object_Name__c/a3U7X000000XLRsUAO/richTextImageFields/Field_Name__c/0EM7X0000009FIf';
do {
    HttpRequest req = new HttpRequest();
    req.setEndpoint(location);
    req.setMethod('GET');
    req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
    HttpResponse res = new Http().send(req);
    System.debug('res: ' + res);
    if (res.getStatusCode() == 302) {
        location = res.getHeader('Location');
        System.debug('location: ' + location);
    } else if (res.getStatusCode() == 200) {
        location = null;
        Blob b = res.getBodyAsBlob();
        for (String key : res.getHeaderKeys()) System.debug(key + ': ' + res.getHeader(key));
        // Return the Blob
        String url = 'data:' + res.getHeader('Content-Type') + ';base64,' + EncodingUtil.base64Encode(b);
        System.debug('url: ' + url);
        return url;
    } else {
        throw new CalloutException(res.getStatus());
    }
} while (location != null);

you may like to use your own Custom_Object_Name__c and Field_Name__c ofc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.