How to convert HTML text to PDF in salesforce using apex with Aspose Cloud APIs

@tyagias001

The ConvertDocument API method converts the HTML file from the request body. It should work in your scenario. However. I will further look into it and will guide you.

Please check the available fonts list on our Cloud server. By default, the ConvertDocument API method uses these fonts for the conversion.

However, if you need some custom fonts for the conversion then you can upload your fonts to a cloud storage folder and pass the cloud storage folder path in API call using fontsLocation Parameter. So yes you can convert the HTML file with traditional Chinese text or Japanese text to PDF.

I am afraid currently the updated Apex sample code is not available. We will try to provide samples in the future. However, meanwhile as shared above you can convert the cURL commands to Apex code.

@tilal.ahmad
So you are saying it has double byte characters support. Nice.

I know i am troubling you on this, but this way to combine everything and put into a apex code is a complex task. I am not complaining/comparing but did go through other products they have samples uploaded on there support and so it becomes so easy for the user to use it. In salesforce we rarely use cURL and so i am also very less aware of it.

I just want to try this once at my end and i can than ask the team to go forward with the licenses.

And offcourse i see you support few other storage vendors also. In this case do you support cloudinary also.

@tyagias001

Thanks for your feedback. Yes we are planning to update and upload the salesforce samples in near future.

We currently support Amazon S3, DropBox, Google Drive Storage, Google Cloud Storage, Windows Azure Storage, FTP Storage along with Aspose internal Storage. However, we do not support cloudinary yet as we have not received any requirement for it. So, we have logged a feature request(STORAGE-153) to investigate the requirement and implement it accordingly.

Thanks for taking the feedback , but I am still trying to put together the apex code. From your article I found the code to get the authentication token but still not aware of the exact method to convert the html text to pdf.

@tyagias001

I am afraid I am not good at Apex. Howerver, please spare us some time, I will try to share sample Apex code for HTML to PFF conversion.

@tyagias001

We have further investigated your requirement and would suggest using to MailMerge Word Document with your HTML/Rich text. Please follow this workflow for this purpose.

Please check the sample Apex code to MailMerge a Word template with HTML along with sample template and output. Hopefully, it will help you to accomplish the task.

template.zip (9.3 KB)

public String ExecuteMailMerege(String FileName, String htmlData, String outFormat) {
     
     try {
            //build URI to Mailmerge using data from cloud storage
            //String strURl = Product.BaseProductUri + '/words/' + FileName + '/MailMerge?destFileName=MailMergeOut.doc&mailMergeDataFile=' + dataFile;
            //build URI to Mailmerge data from string (json/xml)
            String strURl = Product.BaseProductUri + '/words/' + FileName + '/MailMerge?destFileName=MailMergeOut.doc';

            //Mailmerge from data file
            //String strJSON = Utils.ProcessCommand(strURl, 'PUT', null, 'json');
            //Mailmerge from data file
            //XML
			//String htmlData=’<?xml version="1.0" encoding="utf-8" ?><html><head><style type=“text/css”>h2{color:green} .color_red{color:red} .color_green{color:green} .color_magenta{color:magenta} .color_olive{color:olive} .color_teal{color:teal}</style></head><body><h2>Table</h2><table border=“2” cellspacing=“0” cellpadding=“4”><tr><th class=“color_red”>Column 1</th><th class=“color_green”>Column 2</th></tr><tr><td class=“color_magenta”>Value 1.1</td><td class=“color_olive”>Value 1.2</td></tr><tr><td class=“color_teal”>Value 2.1</td></tr></table><h2>Div</h2><div class=“color_olive”>Outer text<div class=“color_magenta”>Inner text</div>Outer text</div><h2>Image</h2><br/><img src=“data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAADUUlEQVR42lWTWUwTURSGaUtIKY5QweISTUzceDGu0Rj1xURjTNQEE+ODGn0hPhBEQdqZztahBbrAtFih1Fprh9IBiVLLErZSU7BUoS7VqNH44ovx0S0ovdfO4Ez04cw9Ofec7/5zzr15NEnkUxSVFx8ObZ1x7nzHN6z9nOhnzOFwWCnECcKoEFbBRrrp6iF/XRvD0BoplkdTuAiIhtt3P3Fu+jJlKlkM1WoXLFjVeSnpXrC94gV3ciJp1X0L1K7+NtDfvXdpj1TmmUwm8QTfLa867T+ceWTSwO5r5b87XNaDEoBrv3p2Ai+AU1Qh5OiDGS4UXi4roAisQHBiYfJS2obAVPMyELYcGxViOIaKcLaNLXzadej5nBUBPXW6hdYW0z4RQOYUXK2tUfr8QeXL0Kn4JKEBk7QWdtrrLggJJEmoCBxVCf50qIaaa0HABFkEPZaLNnGfwPNFGV0u05Y554bvMQoBPLbxs9t9QydJpHP/KayRbsf+pG1NdgTTgDuGXa8dbS41ZtArxaQYT1WlHVqYaloGOcvJIan4X2MdViTl3vExbS+GPfXlvzzutj1LPch9HrYea59t0YIRtAAO+PQuIWYwNKikYty41Iuk/3TvMzsCB9HcQR7msgzgjZs7Z5rLQPR6PojeJW2d3oDCoG/IlwAYqlexbp/i9eB19ziuBoMoAlrR03YZ0G8+0JFhS8EjuhD6zWfuCTEjppcBOKYX1bwaqA5MM2oYZ4pBy7XjrAyY7sPqU01FcNZW/jtwZeXXVpt5u1RM4JhYzHFBddqz5/28fUU2NwngtVUbZUCE79o6x67/MYiXLiSbS8D9xp1vI7znkLvDK07A5/MiT7mzdxMMAsdMqxaiWDHkgzePigBUXy9KTfdWeVKNSjjPrvv5uKkYxszlIHX7eDLeVfkgbt30bt5eAlOOtT9nLRrI03szrOumOtcb4SrTSj2KKfr4nuUZ7kR8HFPAYXLlYqxRl43TGjjTWAhHCC1MNK/+lWA0cJLRgfsh95G/N1H136z7+BCSuHMuMEGVLo4a1XCKKcuO0WXZBw1FcNighmPWbe8jIeeJpdFiCrkHguWUyM92NBKseBut8T92bfsw66z49IyrHH2T5CvlqeCYUvL/ANIZ7+ohXSdWAAAAAElFTkSuQmCC”></body></html>’;
			//Json
			//String htmlData=’{“root”:{“data”:{“format”:“html”,“htmlText”:"<html><head><style type=“text/css”>h2{color:green} .color_red{color:red} .color_green{color:green} .color_magenta{color:magenta} .color_olive{color:olive} .color_teal{color:teal}</style></head><body><h2>Table</h2><table border=“2” cellspacing=“0” cellpadding=“4”><tr><th class=“color_red”>Column 1</th><th class=“color_green”>Column 2</th></tr><tr><td class=“color_magenta”>Value 1.1</td><td class=“color_olive”>Value 1.2</td></tr><tr><td class=“color_teal”>Value 2.1</td></tr></table><h2>Div</h2><div class=“color_olive”>Outer text<div class=“color_magenta”>Inner text</div>Outer text</div><h2>Image</h2><br/><img src=“data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAADUUlEQVR42lWTWUwTURSGaUtIKY5QweISTUzceDGu0Rj1xURjTNQEE+ODGn0hPhBEQdqZztahBbrAtFih1Fprh9IBiVLLErZSU7BUoS7VqNH44ovx0S0ovdfO4Ez04cw9Ofec7/5zzr15NEnkUxSVFx8ObZ1x7nzHN6z9nOhnzOFwWCnECcKoEFbBRrrp6iF/XRvD0BoplkdTuAiIhtt3P3Fu+jJlKlkM1WoXLFjVeSnpXrC94gV3ciJp1X0L1K7+NtDfvXdpj1TmmUwm8QTfLa867T+ceWTSwO5r5b87XNaDEoBrv3p2Ai+AU1Qh5OiDGS4UXi4roAisQHBiYfJS2obAVPMyELYcGxViOIaKcLaNLXzadej5nBUBPXW6hdYW0z4RQOYUXK2tUfr8QeXL0Kn4JKEBk7QWdtrrLggJJEmoCBxVCf50qIaaa0HABFkEPZaLNnGfwPNFGV0u05Y554bvMQoBPLbxs9t9QydJpHP/KayRbsf+pG1NdgTTgDuGXa8dbS41ZtArxaQYT1WlHVqYaloGOcvJIan4X2MdViTl3vExbS+GPfXlvzzutj1LPch9HrYea59t0YIRtAAO+PQuIWYwNKikYty41Iuk/3TvMzsCB9HcQR7msgzgjZs7Z5rLQPR6PojeJW2d3oDCoG/IlwAYqlexbp/i9eB19ziuBoMoAlrR03YZ0G8+0JFhS8EjuhD6zWfuCTEjppcBOKYX1bwaqA5MM2oYZ4pBy7XjrAyY7sPqU01FcNZW/jtwZeXXVpt5u1RM4JhYzHFBddqz5/28fUU2NwngtVUbZUCE79o6x67/MYiXLiSbS8D9xp1vI7znkLvDK07A5/MiT7mzdxMMAsdMqxaiWDHkgzePigBUXy9KTfdWeVKNSjjPrvv5uKkYxszlIHX7eDLeVfkgbt30bt5eAlOOtT9nLRrI03szrOumOtcb4SrTSj2KKfr4nuUZ7kR8HFPAYXLlYqxRl43TGjjTWAhHCC1MNK/+lWA0cJLRgfsh95G/N1H136z7+BCSuHMuMEGVLo4a1XCKKcuO0WXZBw1FcNighmPWbe8jIeeJpdFiCrkHguWUyM92NBKseBut8T92bfsw66z49IyrHH2T5CvlqeCYUvL/ANIZ7+ohXSdWAAAAAElFTkSuQmCC”></body></html>"}}}’;
			String strJSON = Utils.ProcessCommand(strURl, ‘PUT’, htmlData, ‘json’);
			//this.apiResponse = strJSON;
			system.debug(strJSON);
			//prepare signed download link
			String downloadURL = null;
         
         	Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(strJSON);
          	if(params.containsKey('Document')){
          	Map<String, Object> doc = (Map<String, Object>)params.get('Document');
          	String DocName = (String)doc.get('FileName');

          	strURl = Product.BaseProductUri + '/words/' + DocName + '?format=' + outFormat;

          	downloadURL = strURl;
          }
          	return downloadURL;

        }
        
        catch (Exception ex) {
            system.debug(ex);
            return null;
        }   
     
     
    }

@tilal.ahmad
Thanks for all your effort . I feel i am very close. I have two questions here.

  1. What is file name parameter.
  2. What is HtmlData Parameter here.

Now My Input is
String jsonData = ‘

秘密保持契約書 および売主またはそのいずれかは、本契約の日付の前後いずれに提供されたかを問わないすべての情報(以下

’ ;

Output - Should be blob version or base64 encoded or UTF-8 encoded or at least an pdf url which i will convert to base64.

Request - System.HttpRequest[Endpoint=https://api.aspose.cloud/v4.0/words//MailMerge?destFileName=test.pdf, Method=PUT]

response: System.HttpResponse[Status=Not Found, StatusCode=404]

What am i missing here?

Below is my code.

public class asposeMailMerge {

public static string GetJWT(){
    String grant_type = 'client_credentials';
    String client_id= '1ddabfd7-82a1-421f-a051-1d39d487f6c0';
    String client_secret= '7c0e602e6a5c346829e6ceae20070dc4';	
    HttpRequest request = new HttpRequest();
    
    request.setEndpoint('https://api.aspose.cloud/connect/token');
    request.setMethod('GET');                
    request.setHeader('Content-Type', 'application/x-www-form-urlencoded');              
    request.setHeader('Accept', 'application/json');
    
    String body = 'grant_type=' + grant_type + '&client_id=' + client_id + '&client_secret='+ client_secret ;
    request.setBody(body);
    
    Http http = new Http();
    HttpResponse res = http.send(request);
    String jsonInput = res.getBody();
    Map<String, Object> a =(Map<String, Object>)JSON.deserializeUntyped(jsonInput);
    system.debug('JWT Token is: '+a.get('access_token'));
    
    return a.get('access_token').ToString();
}

public static String ProcessCommand(String strURI, String strHttpCommand, String strContent, String ContentType, String accessToken) {
    try {
        HttpRequest request = new HttpRequest();
        Integer len = 0;
        if (strContent != null) {
            request.setBody(strContent);
            len = strContent.length();
        }
        system.debug('httpcommand: ' + strHttpCommand);
        request.setEndpoint(strURI);
        request.setMethod(strHttpCommand);
        
        if (ContentType.toLowerCase() == 'xml')
            request.setHeader('Content-Type', 'application/xml');
        else
            request.setHeader('Content-Type', 'application/json');
        request.setHeader('Content-Length', String.valueOf(len));
        request.setHeader('Accept', 'application/json');
        request.setHeader('Authorization', accessToken);
        request.setTimeout(120000);
        
        Http http = new Http();
        system.debug('request ' + request);
        HttpResponse res = http.send(request);
        system.debug('util response:' + res);
        return res.getBody();
        
    } catch (Exception ex) {
        system.debug('HTTP ERROR' + ex.getMessage());
        system.debug(ex.getStackTraceString());
        return null;
    }
}

public static String ExecuteMailMerege(String FileName, String htmlData, String outFormat) {
    try {
        String strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + FileName + '/MailMerge?destFileName=test.pdf';
        
        //Json
        //String htmlData='{root':{'data':{'format':'html','htmlText':'<html><head><style type=“text/css”>h2{color:green} .color_red{color:red} .color_green{color:green} .color_magenta{color:magenta} .color_olive{color:olive} .color_teal{color:teal}</style></head><body><h2>Table</h2><table border=“2” cellspacing=“0” cellpadding=“4”><tr><th class=“color_red”>Column 1</th><th class=“color_green”>Column 2</th></tr><tr><td class=“color_magenta”>Value 1.1</td><td class=“color_olive”>Value 1.2</td></tr><tr><td class=“color_teal”>Value 2.1</td></tr></table><h2>Div</h2><div class=“color_olive”>Outer text<div class=“color_magenta”>Inner text</div>Outer text</div><h2>Image</h2><br/><img src=“data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAADUUlEQVR42lWTWUwTURSGaUtIKY5QweISTUzceDGu0Rj1xURjTNQEE+ODGn0hPhBEQdqZztahBbrAtFih1Fprh9IBiVLLErZSU7BUoS7VqNH44ovx0S0ovdfO4Ez04cw9Ofec7/5zzr15NEnkUxSVFx8ObZ1x7nzHN6z9nOhnzOFwWCnECcKoEFbBRrrp6iF/XRvD0BoplkdTuAiIhtt3P3Fu+jJlKlkM1WoXLFjVeSnpXrC94gV3ciJp1X0L1K7+NtDfvXdpj1TmmUwm8QTfLa867T+ceWTSwO5r5b87XNaDEoBrv3p2Ai+AU1Qh5OiDGS4UXi4roAisQHBiYfJS2obAVPMyELYcGxViOIaKcLaNLXzadej5nBUBPXW6hdYW0z4RQOYUXK2tUfr8QeXL0Kn4JKEBk7QWdtrrLggJJEmoCBxVCf50qIaaa0HABFkEPZaLNnGfwPNFGV0u05Y554bvMQoBPLbxs9t9QydJpHP/KayRbsf+pG1NdgTTgDuGXa8dbS41ZtArxaQYT1WlHVqYaloGOcvJIan4X2MdViTl3vExbS+GPfXlvzzutj1LPch9HrYea59t0YIRtAAO+PQuIWYwNKikYty41Iuk/3TvMzsCB9HcQR7msgzgjZs7Z5rLQPR6PojeJW2d3oDCoG/IlwAYqlexbp/i9eB19ziuBoMoAlrR03YZ0G8+0JFhS8EjuhD6zWfuCTEjppcBOKYX1bwaqA5MM2oYZ4pBy7XjrAyY7sPqU01FcNZW/jtwZeXXVpt5u1RM4JhYzHFBddqz5/28fUU2NwngtVUbZUCE79o6x67/MYiXLiSbS8D9xp1vI7znkLvDK07A5/MiT7mzdxMMAsdMqxaiWDHkgzePigBUXy9KTfdWeVKNSjjPrvv5uKkYxszlIHX7eDLeVfkgbt30bt5eAlOOtT9nLRrI03szrOumOtcb4SrTSj2KKfr4nuUZ7kR8HFPAYXLlYqxRl43TGjjTWAhHCC1MNK/+lWA0cJLRgfsh95G/N1H136z7+BCSuHMuMEGVLo4a1XCKKcuO0WXZBw1FcNighmPWbe8jIeeJpdFiCrkHguWUyM92NBKseBut8T92bfsw66z49IyrHH2T5CvlqeCYUvL/ANIZ7+ohXSdWAAAAAElFTkSuQmCC”></body></html>"}}}’;
        
		//String jsonData = JSON.serialize('<p style="text-align: center;"><b style="color: rgb(102, 102, 102); font-size: 9pt;">秘密保持契約書 および売主またはそのいずれかは、本契約の日付の前後いずれに提供されたかを問わないすべての情報(以下</b></p>'); 
		            
        String jsonData='{"root":{"data":{"format":"html","htmlText":"&lt;html&gt;&lt;head&gt;&lt;style type=&quot;text/css&quot;&gt;h2{color:green} .color_red{color:red} .color_green{color:green} .color_magenta{color:magenta} .color_olive{color:olive} .color_teal{color:teal}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;h2&gt;Table&lt;/h2&gt;&lt;table border=&quot;2&quot; cellspacing=&quot;0&quot; cellpadding=&quot;4&quot;&gt;&lt;tr&gt;&lt;th class=&quot;color_red&quot;&gt;Column 1&lt;/th&gt;&lt;th class=&quot;color_green&quot;&gt;Column 2&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;color_magenta&quot;&gt;Value 1.1&lt;/td&gt;&lt;td class=&quot;color_olive&quot;&gt;Value 1.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;color_teal&quot;&gt;Value 2.1&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;h2&gt;Div&lt;/h2&gt;&lt;div class=&quot;color_olive&quot;&gt;Outer text&lt;div class=&quot;color_magenta&quot;&gt;Inner text&lt;/div&gt;Outer text&lt;/div&gt;&lt;h2&gt;Image&lt;/h2&gt;&lt;br/&gt;&lt;img src=&quot;data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAADUUlEQVR42lWTWUwTURSGaUtIKY5QweISTUzceDGu0Rj1xURjTNQEE+ODGn0hPhBEQdqZztahBbrAtFih1Fprh9IBiVLLErZSU7BUoS7VqNH44ovx0S0ovdfO4Ez04cw9Ofec7/5zzr15NEnkUxSVFx8ObZ1x7nzHN6z9nOhnzOFwWCnECcKoEFbBRrrp6iF/XRvD0BoplkdTuAiIhtt3P3Fu+jJlKlkM1WoXLFjVeSnpXrC94gV3ciJp1X0L1K7+NtDfvXdpj1TmmUwm8QTfLa867T+ceWTSwO5r5b87XNaDEoBrv3p2Ai+AU1Qh5OiDGS4UXi4roAisQHBiYfJS2obAVPMyELYcGxViOIaKcLaNLXzadej5nBUBPXW6hdYW0z4RQOYUXK2tUfr8QeXL0Kn4JKEBk7QWdtrrLggJJEmoCBxVCf50qIaaa0HABFkEPZaLNnGfwPNFGV0u05Y554bvMQoBPLbxs9t9QydJpHP/KayRbsf+pG1NdgTTgDuGXa8dbS41ZtArxaQYT1WlHVqYaloGOcvJIan4X2MdViTl3vExbS+GPfXlvzzutj1LPch9HrYea59t0YIRtAAO+PQuIWYwNKikYty41Iuk/3TvMzsCB9HcQR7msgzgjZs7Z5rLQPR6PojeJW2d3oDCoG/IlwAYqlexbp/i9eB19ziuBoMoAlrR03YZ0G8+0JFhS8EjuhD6zWfuCTEjppcBOKYX1bwaqA5MM2oYZ4pBy7XjrAyY7sPqU01FcNZW/jtwZeXXVpt5u1RM4JhYzHFBddqz5/28fUU2NwngtVUbZUCE79o6x67/MYiXLiSbS8D9xp1vI7znkLvDK07A5/MiT7mzdxMMAsdMqxaiWDHkgzePigBUXy9KTfdWeVKNSjjPrvv5uKkYxszlIHX7eDLeVfkgbt30bt5eAlOOtT9nLRrI03szrOumOtcb4SrTSj2KKfr4nuUZ7kR8HFPAYXLlYqxRl43TGjjTWAhHCC1MNK/+lWA0cJLRgfsh95G/N1H136z7+BCSuHMuMEGVLo4a1XCKKcuO0WXZBw1FcNighmPWbe8jIeeJpdFiCrkHguWUyM92NBKseBut8T92bfsw66z49IyrHH2T5CvlqeCYUvL/ANIZ7+ohXSdWAAAAAElFTkSuQmCC&quot;&gt;&lt;/body&gt;&lt;/html&gt;"}}}';
        system.debug('jsonData ' + jsonData );
        String strJSON = ProcessCommand(strURl, 'PUT', jsonData, 'json', GetJWT());
        
        system.debug('strJSON @@ ' + strJSON); 
        
        String downloadURL = null;
        
        Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(strJSON);
        
        if(params.containsKey('Document')){
            Map<String, Object> doc = (Map<String, Object>)params.get('Document');
            String DocName = (String)doc.get('FileName');
            
            strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + DocName + '?format=' + outFormat;
            
            downloadURL = strURl;
        }
        return downloadURL;
        
    }
    
    catch (Exception ex) {
        system.debug(ex.getLineNumber() + '- ' + ex.getCause() + '- ' + ex.getMessage() + '- '+  ex.getStackTraceString());
        return null;
    }   
    
    
}

}

@tyagias001

It is MailMerge Template(DOC/DOCX) file name from the cloud storage that will be passed in the API call. First, you need to upload your Template to cloud storage. As suggested above you need to mail merge HTML/Rich Text in a Template and then convert it to PDF. I have also shared a sample MailMerge template in a zip file.

https://api.aspose.cloud/v4.0/words/template.doc/MailMerge?destFileName=test.doc

It is JSON/XML data to populate in MailMerge Template.

String inputText ='秘密保持契約書 および売主またはそのいずれかは、本契約の日付の前後いずれに提供されたかを問わないすべての情報(以下' ;

String jsonData= '{"root":{"data":{"format": "html","htmlText": "' + inputText + '"}}}';

@tyagias001

In addition to the above reply, please note in the above examples we have used Aspose Cloud default storage so we have not used the storage parameter. If you want to use any other supported cloud storage(Amazon S3, DropBox, Google Drive Storage, Google Cloud Storage, Windows Azure Storage, FTP Storage) then you need to pass the storage name as well.

https://api.aspose.cloud/v4.0/words/template.doc/MailMerge?storage=myGoogleAspose&destFileName=Test.doc

@tilal.ahmad
“Error”: {
“Code”: “ErrorItemNotFound”,
“Message”: “Error while loading file ‘template.doc’ from storage: AmazonS3 Storage exception: The specified key does not exist. Bucket ‘aspose.cloud-filestorage-prod’, FilePath ‘848421/baabd63f-e70b-4077-a371-f9bcba28289d/template.doc’”,
“Description”: “Operation Failed. Item Not Found.”,
“InnerError”: {
“Code”: “errorAmazonS3Storage”,
“Message”: “AmazonS3 Storage exception: The specified key does not exist. Bucket ‘aspose.cloud-filestorage-prod’, FilePath ‘848421/baabd63f-e70b-4077-a371-f9bcba28289d/template.doc’”,
“Description”: “Operation Failed. The remote server returned an error: (404) Not Found.”
}
},
“RequestId”: “Root=1-602cb8b6-20df662b3fa7a51b77e522fc”

I am getting above response while doing mail merge.

@tyagias001

It seems the API call is unable to find the target file(template.doc). Please double check that the template.doc is available in your default cloud storage from aspose.cloud dashboard.

@tilal.ahmad
I have put template file there and i am try to build URI to Mailmerge data from string (json/xml) and i am still getting below error.

Error": {
“Code”: “ErrorInvalidInputData”,
“Message”: “Mail merge data is required in request body or you should specify ‘mailMergeDataFile’ parameter.”,
“Description”: “Operation Failed. The input data is not valid.”
},
“RequestId”: “Root=1-602d008e-44a9590029da899b1e0cab49”
}

I am using below code-

String strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + 'template.doc' + '/MailMerge?destFileName=test.doc';

String strJSON = ProcessCommand(strURl, 'PUT', null, 'json', GetJWT());

It is getting difficult for me to execute this… Can you also see what wrong am I doing in the code which I shared above.

@tyagias001

As stated in the error message, you are not passing the MailMerge data in the API call.

Please pass your JSON data(jsonData) to populate in the template. It should resolve the issue.

String strJSON = ProcessCommand(strURl, ‘PUT’, jsonData, ‘json’, GetJWT());

Ok and what would be this datafile? is it the input html.

String strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + 'template.doc' + '/MailMerge?destFileName=test.doc' + '&mailMergeDataFile=' + dataFile;
            //String strJSON = ProcessCommand(strURl, 'PUT', null, 'json', GetJWT());
            //system.debug('strJSON @@ ' + strJSON); 
            //Json
            
    		String inputText = '<p style="text-align: center;"><b style="color: rgb(102, 102, 102); font-size: 9pt;">秘密保持契約書 および売主またはそのいずれかは、本契約の日付の前後いずれに提供されたかを問わないすべての情報(以下</b></p>'; 
			            
            String jsonData= '{"root":{"data":{"format": "html","htmlText": "' + inputText + '"}}}';
            system.debug('jsonData ' + jsonData );
            String strJSON1 = ProcessCommand(strURl, 'PUT', jsonData, 'json', GetJWT());
            
            system.debug('strJSON1 @@ ' + strJSON1); 
            
            String downloadURL = null;
            
            Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(strJSON1);
            
            if(params.containsKey('Document')){
                Map<String, Object> doc = (Map<String, Object>)params.get('Document');
                String DocName = (String)doc.get('FileName');
                
                strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + DocName + '?format=' + outFormat;
                
                downloadURL = strURl;
            }
            return downloadURL;

@tyagias001

Please note the MailMerge API request supports passing Mailmerge data using a data file from cloud storage or JSON/XML data via request body. As per your requirement you need to convert HTML text(stored in a string) to PDF. So I have shared sample code using the request body.

Please pay attention to the sample code shared in my above post. You may amend it as per your need.

....
String strURl = Product.BaseProductUri + '/words/' + FileName + '/MailMerge?destFileName=MailMergeOut.doc';
....
//Json
			//String htmlData=’{“root”:{“data”:{“format”:“html”,“htmlText”:"<html><head><style type=“text/css”>h2{color:green} .color_red{color:red} .color_green{color:green} .color_magenta{color:magenta} .color_olive{color:olive} .color_teal{color:teal}</style></head><body><h2>Table</h2><table border=“2” cellspacing=“0” cellpadding=“4”><tr><th class=“color_red”>Column 1</th><th class=“color_green”>Column 2</th></tr><tr><td class=“color_magenta”>Value 1.1</td><td class=“color_olive”>Value 1.2</td></tr><tr><td class=“color_teal”>Value 2.1</td></tr></table><h2>Div</h2><div class=“color_olive”>Outer text<div class=“color_magenta”>Inner text</div>Outer text</div><h2>Image</h2><br/><img src=“data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAADUUlEQVR42lWTWUwTURSGaUtIKY5QweISTUzceDGu0Rj1xURjTNQEE+ODGn0hPhBEQdqZztahBbrAtFih1Fprh9IBiVLLErZSU7BUoS7VqNH44ovx0S0ovdfO4Ez04cw9Ofec7/5zzr15NEnkUxSVFx8ObZ1x7nzHN6z9nOhnzOFwWCnECcKoEFbBRrrp6iF/XRvD0BoplkdTuAiIhtt3P3Fu+jJlKlkM1WoXLFjVeSnpXrC94gV3ciJp1X0L1K7+NtDfvXdpj1TmmUwm8QTfLa867T+ceWTSwO5r5b87XNaDEoBrv3p2Ai+AU1Qh5OiDGS4UXi4roAisQHBiYfJS2obAVPMyELYcGxViOIaKcLaNLXzadej5nBUBPXW6hdYW0z4RQOYUXK2tUfr8QeXL0Kn4JKEBk7QWdtrrLggJJEmoCBxVCf50qIaaa0HABFkEPZaLNnGfwPNFGV0u05Y554bvMQoBPLbxs9t9QydJpHP/KayRbsf+pG1NdgTTgDuGXa8dbS41ZtArxaQYT1WlHVqYaloGOcvJIan4X2MdViTl3vExbS+GPfXlvzzutj1LPch9HrYea59t0YIRtAAO+PQuIWYwNKikYty41Iuk/3TvMzsCB9HcQR7msgzgjZs7Z5rLQPR6PojeJW2d3oDCoG/IlwAYqlexbp/i9eB19ziuBoMoAlrR03YZ0G8+0JFhS8EjuhD6zWfuCTEjppcBOKYX1bwaqA5MM2oYZ4pBy7XjrAyY7sPqU01FcNZW/jtwZeXXVpt5u1RM4JhYzHFBddqz5/28fUU2NwngtVUbZUCE79o6x67/MYiXLiSbS8D9xp1vI7znkLvDK07A5/MiT7mzdxMMAsdMqxaiWDHkgzePigBUXy9KTfdWeVKNSjjPrvv5uKkYxszlIHX7eDLeVfkgbt30bt5eAlOOtT9nLRrI03szrOumOtcb4SrTSj2KKfr4nuUZ7kR8HFPAYXLlYqxRl43TGjjTWAhHCC1MNK/+lWA0cJLRgfsh95G/N1H136z7+BCSuHMuMEGVLo4a1XCKKcuO0WXZBw1FcNighmPWbe8jIeeJpdFiCrkHguWUyM92NBKseBut8T92bfsw66z49IyrHH2T5CvlqeCYUvL/ANIZ7+ohXSdWAAAAAElFTkSuQmCC”></body></html>"}}}’;
			String strJSON = Utils.ProcessCommand(strURl, ‘PUT’, htmlData, ‘json’);
....

In the above code, MailMerge is not passed in the uri.

        String strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + 'template.doc' + '/MailMerge?destFileName=MailMergeOut(1).doc';

		String inputText = '<p style="text-align: center;"><b style="color: rgb(102, 102, 102); font-size: 9pt;">秘密保持契約書 および売主またはそのいずれかは、本契約の日付の前後いずれに提供されたかを問わないすべての情報(以下</b></p>'; 
		            
        String jsonData= '{"root":{"data":{"format": "html","htmlText": "' + inputText + '"}}}';
        system.debug('jsonData ' + jsonData );
        String strJSON1 = ProcessCommand(strURl, 'PUT', jsonData, 'json', GetJWT());

        
        system.debug('strJSON1 @@ ' + strJSON1); 
        
        String downloadURL = null;
        
        Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(strJSON1);
        
        if(params.containsKey('Document')){
            Map<String, Object> doc = (Map<String, Object>)params.get('Document');
            String DocName = (String)doc.get('FileName');
            
            strURl = 'https://api.aspose.cloud/v4.0' + '/words/' + DocName + '?format=' + outFormat;
            
            downloadURL = strURl;
        }
        return downloadURL;

Can you tell me what’s wrong in above code. I am getting below error -

“Message”: “After parsing a value an unexpected character was encountered: t. Path ‘root.data.htmlText’, line 1, position 57.”

@tilal.ahmad
Input data is shown in above code.

@tyagias001

Please note you need to escape the HTML string. As HTML text is escaped in above shared example and mentioned in the Insert HTML documentation. So the HTML input text would be like as below.

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b style=&quot;color: rgb(102, 102, 102); font-size: 9pt;&quot;&gt;秘密保持契約書 および売主またはそのいずれかは、本契約の日付の前後いずれに提供されたかを問わないすべての情報(以下&lt;/b&gt;&lt;/p&gt;

@tilal.ahmad

So are you saying that we need to makes changes to input string(which is a user entry rich text field).?
In that case again lot of backend processing needs to happen and have to write code for escaping HTML characters?

Is they a better way of doing this.?

@tyagias001

I am afraid there is no other option available to add HTML text in a Word document and then convert it to PDF. Other options are file conversion. I think you can simply replace following characters in HTML string using replace method.

" is replaced with &quot;
& is replaced with &amp;
< is replaced with &lt;
> is replaced with &gt;