Link Search Menu Expand Document

Merge Documents From SFDC record - Salesforce

PDF Merge sample in Salesforce demonstrating ‘Merge Documents From SFDC record’

MergeDocumentsFromUploadedFiles.cls
public class MergeDocumentsFromUploadedFiles {
    
    String API_KEY = '***************';  
    String[] fileName = new String[] {'images-and-documents', 'Input', 'sample1'}; // File name which is available in salesforce Files.
    string destinationFile =  'MergeResultByUpload'; //This is the Desitantion File Name.
   
    List<String> urlList = new List<String>();
    public void startProcessing()
    {
        try
        {
            for(String fname : fileName)
            {
                ContentVersion cv = [select Title, VersionData from ContentVersion where Title = :fname limit 1];
                Blob SourceFile  = cv.VersionData;
                //1. Prepare URL for "Get Presigned URL" API call
                string url = 'https://api.pdf.co/v1/file/upload/get-presigned-url?contenttype=application/octet-stream&name=:fname'; 
                HttpRequest req = new HttpRequest();
                req.setHeader('x-api-key', API_KEY);
                req.setEndpoint(url);
                req.setMethod('GET');
                req.setTimeout(60000);
                Http http = new Http();
                HTTPResponse res = http.send(req);
                if(res.getStatusCode() == 200) 
                {
                    System.Debug('res ' + res);
                    Map<String, Object> deserializedBody =  (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
                    Boolean isError = Boolean.ValueOf(deserializedBody.get('error'));
                    if(isError == false)
                    {
                        // Get URL to use for the file upload
                        String uploadUrl = String.ValueOf(deserializedBody.get('presignedUrl'));
                        // Get URL of uploaded file to use with later API calls
                        String uploadedFileUrl = String.ValueOf(deserializedBody.get('url'));
                        SYstem.debug('uploadedFileUrl :: '+uploadedFileUrl);
                        // 2. UPLOAD THE FILE TO CLOUD.
                        if(uploadFile(API_KEY, uploadUrl, SourceFile))
                        {
                            // Merge Documents and download
                            urlList.add(uploadedFileUrl);  
                            System.debug('urlList ' + urlList);
                            //System.assert(false, ' urlList ' + urlList);
                        }
                    }
                }
                else
                {
                    System.debug('Error Response ' + res.getBody());
                    System.Debug(' Status ' + res.getStatus());
                    System.Debug(' Status Code' + res.getStatusCode());
                    System.Debug(' Response String' + res.toString());
                } 
            }
            if (urlList.size() > 0)
            {                
                // 2. MERGE UPLOADED PDF DOCUMENTS
                MergeDocToPDF(urlList);
            }
        }
        catch(Exception ex)
        {
            String errorBody = 'Message: ' + ex.getMessage() + ' -- Cause: ' + ex.getCause() + ' -- Stacktrace: ' + ex.getStackTraceString();
            System.Debug(errorBody);
        }
        
    }   
    
    @TestVisible
    public static boolean uploadFile(String API_KEY, String url, Blob sourceFile)
    {
        HttpRequest req = new HttpRequest();
        req.setHeader('x-api-key', API_KEY);
        req.setHeader('Content-Type', 'application/octet-stream');
        req.setEndpoint(url);
        req.setMethod('PUT');
        req.setTimeout(60000);
        req.setBodyAsBlob(sourceFile);
        Http http = new Http();
        HTTPResponse res = http.send(req);
        if(res.getStatusCode() == 200) 
        {
            System.Debug(res.getBody());
            return true;
        }
        else
        {
            System.debug('Error Response ' + res.getBody());
            System.Debug(' Status ' + res.getStatus());
            System.Debug(' Status Code' + res.getStatusCode());
            System.Debug(' Response String' + res.toString());
            return false;
        }
    }
    
    public void MergeDocToPDF(List<String> uploadedFileUrl)
    {
        try
        {
            string filesUrl = string.join(uploadedFileUrl,',');            
            Map<string, Object> parameters = new Map<string, Object>();
            parameters.put('url', filesUrl);
            string jsonPayload = Json.serialize(parameters);
            
            string url = 'https://api.pdf.co/v1/pdf/merge2';
            HttpRequest req1 = new HttpRequest();
            req1.setBody(jsonPayload);
            req1.setHeader('x-api-key', API_KEY);
            req1.setHeader('Content-Type', 'application/json');
            req1.setEndpoint(url);
            req1.setMethod('POST');
            req1.setTimeout(60000);
            Http http = new Http();
            HTTPResponse res1 = http.send(req1);
            if(res1.getStatusCode() == 200) 
            {
                Map<String, Object> deserializedBody =  (Map<String, Object>)JSON.deserializeUntyped(res1.getBody());
                Boolean isError = Boolean.ValueOf(deserializedBody.get('error'));
                if(isError == false)
                {
                    SYstem.debug('res1.getBody() :: '+res1.getBody());
                    String urlVal = (String)deserializedBody.get('url');
                    downloadPDFAndStore(urlVal, destinationFile);
                }
            }
            else
            {
                System.debug('Success Response ' + res1.getBody());
                System.Debug(' Status ' + res1.getStatus());
                System.Debug(' Status Code' + res1.getStatusCode());
                System.Debug(' Status String' + res1.toString());
            }
        }
        catch(Exception ex)
        {
            String errorBody = 'Message: ' + ex.getMessage() + ' -- Cause: ' + ex.getCause() + ' -- Stacktrace: ' + ex.getStackTraceString();
            System.Debug(errorBody);
        }
    }
    
    @TestVisible
    private static void downloadPDFAndStore(String extFileUrl, String DestinationFile)
    {
        Http h = new Http(); 
        HttpRequest req = new HttpRequest(); 
        extFileUrl = extFileUrl.replace(' ', '%20'); 
        req.setEndpoint(extFileUrl); 
        req.setMethod('GET'); 
        req.setHeader('Content-Type', 'application/pdf');
        req.setCompressed(true); 
        req.setTimeout(60000); 
        //Now Send HTTP Request
        HttpResponse res  = h.send(req); 
        if(res.getStatusCode() == 200) 
        {
            blob fileContent = res.getBodyAsBlob();
            ContentVersion conVer = new ContentVersion();
            conVer.ContentLocation = 'S'; // to use S specify this document is in Salesforce, to use E for external files
            conVer.PathOnClient = 'result' + '.pdf'; // The files name, extension is very important here which will help the file in preview.
            conVer.Title = DestinationFile; // Display name of the files
            conVer.VersionData = fileContent;
            insert conVer;
            System.Debug('Success');
        }
        else
        {
            System.debug('Error Response ' + res.getBody());
            System.Debug(' Status ' + res.getStatus());
            System.Debug(' Status Code' + res.getStatusCode());
            System.Debug(' Response String' + res.toString());
        }
    }
}
MergeDocumentsFromUploadedFilesTest.cls
@isTest
private class MergeDocumentsFromUploadedFilesTest {

    private static testmethod void MergeDocToPDFTest(){
        List<ContentVersion> cvList = new List<ContentVersion>();
        ContentVersion con = new ContentVersion();
        con.Title = 'images-and-documents';
        con.VersionData=Blob.valueOf('images-and-documents');
        con.PathOnClient = 'images-and-documents.zip';
        cvList.add(con);
        
        ContentVersion con1 = new ContentVersion();
        con1.Title = 'Input';
        con1.VersionData=Blob.valueOf('Input');
        con1.PathOnClient = 'Input.xls';
        cvList.add(con1);
        
        ContentVersion con2 = new ContentVersion();
        con2.Title = 'sample1';
        con2.VersionData=Blob.valueOf('sample1');
        con2.PathOnClient = 'sample1.pdf';
        cvList.add(con2);
        
        insert cvList;
        
        Test.setMock(HttpCalloutMock.class, new MergeDocToPDFMock());
        Test.startTest();
        MergeDocumentsFromUploadedFiles mdp = new MergeDocumentsFromUploadedFiles();
		mdp.startProcessing();        
        Test.stopTest();
    }
    
    
    private static testmethod void MergeDocToPDFTestforCatch(){
        Test.startTest();       
        MergeDocumentsFromUploadedFiles mdp = new MergeDocumentsFromUploadedFiles();
		mdp.startProcessing();        
        Test.stopTest();    
    }
    
    private static testmethod void downloadPDFAndStoreTest(){
        Test.setMock(HttpCalloutMock.class, new MergeDocToPDFMock());
        Test.startTest();
        MergeDocumentsFromUploadedFiles.downloadPDFAndStore('https://pdf-temp-files.s3.amazonaws.com/3ec287356c0b4e02b5231354f94086f2/result.pdf', 'result.pdf');        
        Test.stopTest();
    }
    
    private static testmethod void downloadPDFAndStoreTestforCatch(){
        Test.setMock(HttpCalloutMock.class, new MergeDocToPDFMock());
        Test.startTest();        
        List<String> fileUrl = new List<String>();
        fileUrl.add('https://bytescout-com.s3-us-west-2.amazonaws.com/files/demo-files/cloud-api/pdf-merge/sample1.pdf');
        MergeDocumentsFromUploadedFiles mergeDoc = new MergeDocumentsFromUploadedFiles();
        mergeDoc.MergeDocToPDF(fileUrl);        
        Test.stopTest();
    }
    
    private static testmethod void uploadFileforElse(){
        Test.setMock(HttpCalloutMock.class, new MergeDocToPDFMockForError());
        Test.startTest();
        Blob sourceFile= Blob.valueOf('testData');
        MergeDocumentsFromUploadedFiles.uploadFile('testAPI', 'testUrl', sourceFile);        
        Test.stopTest();
    }
    
    private static testmethod void MergeDocToPDFTestforCatch1(){
        Test.startTest(); 
        List<String> fileUrl = new List<String>();
        fileUrl.add('https://bytescout-com.s3-us-west-2.amazonaws.com/files/demo-files/cloud-api/pdf-merge/sample1.pdf');
        MergeDocumentsFromUploadedFiles mdp = new MergeDocumentsFromUploadedFiles();
		mdp.MergeDocToPDF(fileUrl);        
        Test.stopTest();    
    }
    
    public class MergeDocToPDF implements HttpCalloutMock{
        public HTTPResponse respond(HTTPRequest req) {
            String testBody = '{"url":"https://pdf-temp-files.s3.amazonaws.com/3ec287356c0b4e02b5231354f94086f2/result.pdf","error":false,"status":200,"name":"result.pdf","remainingCredits":98465}';
            HttpResponse res = new HttpResponse();
            res.setHeader('Content-Type', 'application/json;charset=UTF-8');
            res.setBody(testBody);
            res.setStatusCode(200);
            return res;
        }
    }
    
    public class MergeDocToPDFMock implements HttpCalloutMock {
        public HTTPResponse respond(HTTPRequest req) {
            HttpResponse res = new HttpResponse();
            String testBody = '{"presignedUrl":"https://pdf-temp-files.s3-us-west-2.amazonaws.com/0c72bf56341142ba83c8f98b47f14d62/test.pdf?X-Amz-Expires=900&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIZJDPLX6D7EHVCKA/20200302/us-west-2/s3/aws4_request&X-Amz-Date=20200302T143951Z&X-Amz-SignedHeaders=host&X-Amz-Signature=8650913644b6425ba8d52b78634698e5fc8970157d971a96f0279a64f4ba87fc","url":"https://pdf-temp-files.s3-us-west-2.amazonaws.com/0c72bf56341142ba83c8f98b47f14d62/test.pdf?X-Amz-Expires=3600&x-amz-security-token=FwoGZXIvYXdzEGgaDA9KaTOXRjkCdCqSTCKBAW9tReCLk1fVTZBH9exl9VIbP8Gfp1pE9hg6et94IBpNamOaBJ6%2B9Vsa5zxfiddlgA%2BxQ4tpd9gprFAxMzjN7UtjU%2B2gf%2FKbUKc2lfV18D2wXKd1FEhC6kkGJVL5UaoFONG%2Fw2jXfLxe3nCfquMEDo12XzcqIQtNFWXjKPWBkQEvmii4tfTyBTIot4Na%2BAUqkLshH0R7HVKlEBV8btqa0ctBjwzwpWkoU%2BF%2BCtnm8Lm4Eg%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA4NRRSZPHEGHTOA4W/20200302/us-west-2/s3/aws4_request&X-Amz-Date=20200302T143951Z&X-Amz-SignedHeaders=host;x-amz-security-token&X-Amz-Signature=243419ac4a9a315eebc2db72df0817de6a261a684482bbc897f0e7bb5d202bb9","error":false,"status":200,"name":"test.pdf","remainingCredits":98145}';
            res.setHeader('Content-Type', 'application/json');
            res.setBody(testBody);
            res.setStatusCode(200);
            return res;
        }
    }
    
    public class MergeDocToPDFMockForError implements HttpCalloutMock {
        public HTTPResponse respond(HTTPRequest req) {
            HttpResponse res = new HttpResponse();
            String testBody = '{"presignedUrl":"https://pdf-temp-files.s3-us-west-2.amazonaws.com/0c72bf56341142ba83c8f98b47f14d62/test.pdf?X-Amz-Expires=900&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIZJDPLX6D7EHVCKA/20200302/us-west-2/s3/aws4_request&X-Amz-Date=20200302T143951Z&X-Amz-SignedHeaders=host&X-Amz-Signature=8650913644b6425ba8d52b78634698e5fc8970157d971a96f0279a64f4ba87fc","url":"https://pdf-temp-files.s3-us-west-2.amazonaws.com/0c72bf56341142ba83c8f98b47f14d62/test.pdf?X-Amz-Expires=3600&x-amz-security-token=FwoGZXIvYXdzEGgaDA9KaTOXRjkCdCqSTCKBAW9tReCLk1fVTZBH9exl9VIbP8Gfp1pE9hg6et94IBpNamOaBJ6%2B9Vsa5zxfiddlgA%2BxQ4tpd9gprFAxMzjN7UtjU%2B2gf%2FKbUKc2lfV18D2wXKd1FEhC6kkGJVL5UaoFONG%2Fw2jXfLxe3nCfquMEDo12XzcqIQtNFWXjKPWBkQEvmii4tfTyBTIot4Na%2BAUqkLshH0R7HVKlEBV8btqa0ctBjwzwpWkoU%2BF%2BCtnm8Lm4Eg%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA4NRRSZPHEGHTOA4W/20200302/us-west-2/s3/aws4_request&X-Amz-Date=20200302T143951Z&X-Amz-SignedHeaders=host;x-amz-security-token&X-Amz-Signature=243419ac4a9a315eebc2db72df0817de6a261a684482bbc897f0e7bb5d202bb9","error":false,"status":200,"name":"test.pdf","remainingCredits":98145}';
            res.setHeader('Content-Type', 'application/json');
            res.setBody(testBody);
            res.setStatusCode(201);
            return res;
        }
    }

}

PDF.co Web API: the Web API with a set of tools for documents manipulation, data conversion, data extraction, splitting and merging of documents. Includes image recognition, built-in OCR, barcode generation and barcode decoders to decode bar codes from scans, pictures and pdf.

Get your PDF.co API key here!

Download Source Code (.zip)

return to the previous page explore PDF Merge endpoint