Salesforce doesn't have direct method to read files. We can do it either by external service written in Java/.Net or using javascript.
We will be discussing to parse data coming in zipped XML over http from 3-party API and populate data in salesforce. Basically, there were three main tasks:
Task 3:
Task 2:
Key points to remember:
We will be discussing to parse data coming in zipped XML over http from 3-party API and populate data in salesforce. Basically, there were three main tasks:
- Collect http reponse from API in form of zipped xml.
 - Unzip that response and get xml string out of it.
 - Parse xml string to insert data.
 
Main focus of this blog is to accomplish Task 2 but first let see the key points for tasks 1 & 3:
Task 1: 
- You just need to call response.getBodyAsBlob() when ever response is in form of file.
 - Then, you need to convert bolb into string using code syntax:
 
String xmlzippedFile = EncodingUtil.base64Encode(res.getBodyAsBlob());
Task 3:
- If your XML string contains <![CDATA[value]]> tag then make use of XmlStreamReader class.
 - If not, then you can either use Document class or XmlStreamReader class.
 
Task 2:
Main task to unzip xml file, the steps to achieve are mentioned below:
- Add jZip.js file to static resource (download)
 - Add inflate.js file to static resource. (download)
 - Open notepad, paste below code and save as file.js file and upload to static resource.
 
var filearr = [];
/* Main unzip function */
function unzip(zip){
 model.getEntries(zip, function(entries) {
  entries.forEach(function(entry) {
   model.getEntryFile(entry, "Blob");
  });
 });
}
//model for zip.js
var model = (function() {
 var URL = window.webkitURL || window.mozURL || window.URL;
 var acount = 0;
 var bcount = 0;
 //compile a list of file extensions and content types
 var mapping = {
   "pdf":"application/pdf",
   "zip":"application/zip",
   "rar":"application/rar",
   "json":"application/json",
   "mid":"audio/mid",
   "mp3":"audio/mpeg",
   "bmp":"image/bmp",
   "gif":"image/gif",
   "png":"image/png",
   "jpg":"image/jpeg",
   "jpeg":"image/jpeg",
   "svg":"image/svg+xml",
   "xml":"text/xml"
  }
 return {
  getEntries : function(file, onend) {
   zip.createReader(new zip.BlobReader(file), function(zipReader) {
    zipReader.getEntries(onend);
   }, onerror);
  },
  getEntryFile : function(entry, creationMethod, onend, onprogress) {
   acount++;
   var writer, zipFileEntry;
   function getData() {
    entry.getData(writer, function(blob) {
     bcount++;
     filearr.push(blob);
     if(acount == bcount){
      //your vf page method
      waitForProcess();
     }
    }, onprogress);
   }
   var extension = entry.filename.substring(entry.filename.indexOf(".")+1);
   var mime = mapping[extension] || 'text/plain';
   writer = new zip.BlobWriter(mime);
   getData();
  }
 };
 })();
- Create a VF page and include reference to jZip.js and file.js
 - Create a button on VF page to invoke a javascript remoting method which returns a string from Task 1. (Or you can also place a input file element with button if you just want to upload zipped from client machine).
 
<!-- place after page start-->
    <meta charset="utf8" />       
     <apex:includeScript value="{!URLFOR($Resource.jQuery, '')}"/>
    <apex:includeScript value="{!URLFOR($Resource.zip, '')}"/>
    
    <script>
    
    $( document ).ready(function() {
        //Call loading
        requestFile();            
    });
    
    function base64toBlob(base64Data, contentType) {
        contentType = contentType || '';
        var sliceSize = 1024;
        var byteCharacters = atob(base64Data);
        var bytesLength = byteCharacters.length;
        var slicesCount = Math.ceil(bytesLength / sliceSize);
        var byteArrays = new Array(slicesCount);
    
        for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
            var begin = sliceIndex * sliceSize;
            var end = Math.min(begin + sliceSize, bytesLength);
    
            var bytes = new Array(end - begin);
            for (var offset = begin, i = 0 ; offset < end; ++i, ++offset) {
                bytes[i] = byteCharacters[offset].charCodeAt(0);
            }
            byteArrays[sliceIndex] = new Uint8Array(bytes);
        }
        return new Blob(byteArrays, { type: contentType });
    }
    
    function requestFile() {
            var param = 5; //set your param to pass in method
            Visualforce.remoting.Manager.invokeAction(
            '{!$RemoteAction.APEX_PAGE_CONTROLLER_NAME(GLOBAL).methodName}',
            param,
            function(result, event){
                if (event.status) {
                    //call unzip method
                    unzip(base64toBlob(result, ''));
                } else if (event.type === 'exception') {
                    console.log(event.message);
                }
            },  
            {escape: true}
        );
    }
    
    var xmlStrResult = [];
    var isExecuted = false;
    var timerVal;
    
       //your vf page method
function waitForProcess(){
        console.log('call timer');
        timerVal = setInterval('prepareXMLString()', 10);        
    }
    
    function prepareXMLString() {
        if(!isExecuted){            
            $.each(filearr, function(index, file){
                var reader = new FileReader();  // Create a FileReader object
                
                reader.onload = function() {    // Define an event handler
                    try {
                        var xmlDoc = $.parseXML(reader.result);
                        var xmlString = (new XMLSerializer()).serializeToString(xmlDoc);
                        xmlStrResult.push(xmlString); // Display file contents
                    }catch(err) {
                        //TODO
                    }       
                }
                reader.readAsText(file);
                isExecuted = true;
            });
        }
        
        if(xmlStrResult.length != 0){
            clearInterval(timerVal);
            $('#showData').val(xmlStrResult[0]);
            console.log('Done');          
        }
    }
    </script>
    
    <apex:pageBlock >
        <apex:pageBlockSection columns="1" title="Your XML string">
            <apex:pageBlockSectionItem >
               <textarea id="showData" name="showData" rows="30" cols="150">
               Please wait....
               </textarea>
            </apex:pageBlockSectionItem>
        </apex:pageBlockSection>
    </apex:pageBlock>
    
    <apex:includeScript value="{!$Resource.file}" loadOnReady="true"/>
<!-- place before page ends-->
Key points to remember:
- Remoting is required, when you get file from apex controller as http response or from attachment/static resource.
 - In case of input file element, pass file directly to unzip() method.
 
Happy coding :) !!
Hi,
ReplyDeleteSyntax error is coming while i am using the above code as
Syntax error. Missing '}'
Please clarify me on this one...
Thanks in advance