String length exceeds maximum: 6000000

  • Are there any work arounds for this issue?

    I'm trying to upload a file(attachment) to an 3rd party REST API Service. It works fine until my file sizes get about ~5 mb. Then I start getting the following error:

    common.apex.runtime.impl.ExecutionException: String length exceeds maximum: 6000000

    The code that I'm using is a little hacky due to the requirements of the external service (must be multipart, does not accept base64).

    Pretty much it takes the contents of the attachment blob, and combines them with the multipart header then puts them back into a blob.

    Here's the code I'm using. There are some statics that I left out but you get the point.

    public static void UploadAttachment(Attachment attachment, String folder){
    
        String boundary = '----------------------------741e90d31eff';
        String header = '--'+boundary+'\nContent-Disposition: form-data; name="file"; filename="'+attachment.name+'";\nContent-Type: application/octet-stream';
        String footer = '\r\n--'+boundary+'--';              
        String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\r\n\r\n'));
        while(headerEncoded.endsWith('=')){
            header+=' ';
            headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\r\n\r\n'));
        }
        String bodyEncoded = EncodingUtil.base64Encode(attachment.body);
        String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
    
        Blob bodyBlob = null;
        String last4Bytes = bodyEncoded.subString(bodyEncoded.length()-4,bodyEncoded.length());
        if(last4Bytes.endsWith('=')){
            Blob decoded4Bytes = EncodingUtil.base64Decode(last4Bytes);
            HttpRequest tmp = new HttpRequest();
            tmp.setBodyAsBlob(decoded4Bytes);
            String last4BytesFooter = tmp.getBody()+footer;   
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded.subString(0,bodyEncoded.length()-4)+EncodingUtil.base64Encode(Blob.valueOf(last4BytesFooter)));
        }
        else{
            bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
        }
    
        HttpRequest req = new HttpRequest();
        req.setHeader('Authorization', authorizationData);
        req.setHeader('Content-Type','multipart/form-data; boundary='+boundary);
        req.setMethod('POST');
        req.setEndpoint(server+storageService+'/'+folder);
        req.setBodyAsBlob(bodyBlob);
        req.setTimeout(120000);
    
        Http http = new Http();
        HTTPResponse res = http.send(req);
    }
    

    Code modified from this blog post

    Is this an future method? If not, I think this limit is there as a quick way to avoid going over the heap size of 6MB. It's 12mb in future and batch contexts.

    Agreed. Check http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_gov_limits.htm for more limit information. I don't know why you didn't hit the 3MB limit on HTTP requests - ("Maximum size of callout request or response (HTTP request or Web services call)" from the URL I referenced - so that's pretty interesting.

    Perhaps the 6M string length limit already corresponds to the 12Mbyte heap limit as AFAIK an Apex string is a JVM string using 2 bytes per character. But as David mentions there are other limits to run foul of in any case. Apex doesn't have streaming IO classes so large data volumes are always going to be problematic.

    May be you should use third party ETL tool like Cast Iron to pull your attachment from SFDC and push it to your destination system. If you do not want to invest in ETL tool then you can write your won scrip that will pull this attachments from SFDC and push it into destination system using the API.

    The simplest solution ended up being proxying it through a Node server. Just pipe the response straight back to saleforce.

    What about getting the file upload size increased? I believe the max upload size can be set to 25MB depending on the use case.

    I think this string length error is a different hard limit than the file upload size.

  • Unfortunately your SOL when it comes to that sort of limit, you're only route is going to be moving the operation off Salesforce.

    One option would be to create a heroku app with a single endpoint that takes the attachment Id. The endpoint can then retrieve the attachment and then upload it to the 3rd party server.

    crazy... that's exactly what I ended up doing ;)

    @Ralph Callaway, I am facing same error how can i do same thing using heroku app, can you provide me any sample code for this. I am sending document using REST API into netdocuments, but it document is too large then i am getting "String length exceeds maximum: 12000000" this error. I know this is salesforce string limit and we can't bypass it but the way you told is seems possible to send document by bypassing this error using heroku app.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM