Multipart/form-Data in Salesforce Integration | The Developer Guide

Does Grandmother say you can't post a Multipart/structure information utilizing an HttpRequest in APEX

All things considered, on the off chance that she says this now you can reveal to her this is not any more obvious! 

All come from a CloudSpokes challenge (here is the connection)… at the hour of beginning the test I was certain beyond a shadow of a doubt I would have wound up the test in under a day: HTTP gets/posts are not a major issue in APEX… well so it appeared. 

To finish the test you needed to settle on 4 REST decisions (login, book another transfer, transfer the record, set authorizations): during testing the last advance consistently fizzled

This was the first occasion when I hopped before this issue. 

dont miss out iconDon't forget to check out: Salesforce LMS Integration, Train All Your Sales Employees at One Go!

In the event that you would prefer not to understand what I went, straightforwardly here. 

The primary thing I noted was that you can't send a base64 encoded document to a worker anticipating a twofold record. It wasn't that conspicuous to me, since I've never battled with document encoding.

Utilizing distinctive sort of irregular encoded information (other that "AA==") the aftereffects of encoding, blobbing, httpRequesting (??!!), is consistently the equivalent. 

This is the thing that I required: 

  1. Translate the last 4 bytes in mass 
  2. Add it into a HttpRequest utilizing the "setBodyAsBlob()" 
  3. Get the body as a string with "getBody()" 
  4. Combine this string with the footer 
  5. base64 encode the subsequent string 
  6. Combine the base64 encoding of header, record body (from 0 to N-fourth byte), past consolidated string 
  7. base64 unencoding the subsequent string 
  8. Here you are the Blob you required!

dont miss out iconCheck out another amazing blog by Aditya here: Approval Process in Salesforce - Developer Guide

Main Code:

public static GetFile {
    public static void uploadFile(){
        ContentVersion conDoc =  [SELECT Id, Title,      VersionData FROM ContentVersion limit 1];
        // Repost of code  with fix for file corruption issue
        // Orignal code postings and explanations     
        // Extra changes remarked GW: that fix issue with periodic debasement of records
        String boundary = '----------------------------741e90d31eff';
        String header = '--'+boundary+'nContent-Disposition: form-data; name="file"; filename="'+file_name+'";nContent-Type: application/octet-stream';
        // GW: Does not prepend footer by nn, we will see why in a second
        // String footer = 'rn--'+boundary+'--';
        String footer = '--'+boundary+'--';        
        String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'rnrn'));
            header+=' ';
            headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'rnrn'));
        String bodyEncoded = EncodingUtil.base64Encode(file_body);
        // GW: Do not encode footer yet
        // String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
        Blob bodyBlob = null;
        String last4Bytes = bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
        // GW: Replacing this entire section
            Blob decoded4Bytes = EncodingUtil.base64Decode(last4Bytes);
            HttpRequest tmp = new HttpRequest();
            String last4BytesFooter = tmp.getBody()+footer;  
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded.substring(0,bodyEncoded.length()-4)+EncodingUtil.base64Encode(Blob.valueOf(last4BytesFooter)));
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
        // GW: substitution area to dispose of cushioning without debasing information
        if(last4Bytes.endsWith('==')) {
            /The '==' succession shows that the last gathering contained just a single 8 digit byte 
            /8 digit twofold portrayal of CR is 001100101 
            /8 digit twofold portrayal of LF is 001100101 
            /Stitch them together and afterward from the correct split them into 6 bit lumps 
            /001100101  gets 0000 001100101 001010 
            /Note the initial 4 pieces 0000 are indistinguishable from the cushioning used to encode the 
            /second unique 6 bit piece, this is helpful it implies we can hard code the reaction in 
            /The decimal estimations of 001100101 001100101 are 52 10 
            /The base64 planning estimations of 52 10 are 0 K 
            /Therefore, we supplant == with 0K 
            /Note: if utilizing nn rather than rn supplant == with 'alright'
            last4Bytes = last4Bytes.substring(0,2) + '0K';
            bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;       
            String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
        } else if(last4Bytes.endsWith('=')) {
            // '=' demonstrates that encoded information previously contained two out of 3x 8 digit bytes
            // for the existing data.
            // The Decimal value of 001101 is 13
            // The base64 value of 13 is N
            // Therefore, we replace = with N       
            last4Bytes = last4Bytes.substring(0,3) + 'N';
            bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
            // We have appended the CR e.g. r, 
            footer = 'n' + footer;
            String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);         
        } else {
            // Prepend the CR LF to the footer
            footer = 'rn' + footer;
            String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded); 
        HttpRequest req = new HttpRequest();
        req.setHeader('Content-Type','multipart/form-data; boundary='+boundary);
        Http http = new Http();
        HTTPResponse res = http.send(req);



Popular Salesforce Blogs