Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Recently one of our customers asked me about PI capability of handling PDFs. This discussion really got interesting when we started scoping requirement. Just handling PDFs turned out like PI will receive multiple images as base64 encoded string in payload. PI will merge these image file, convert it into PDF and then long list of DOs and Don’ts ultimately send base64 encoded pdf file to 3rd party application.

My experience with PDF till that point of time was restricted to moving pdf files from one folder to another using AAE so I thought of creating POC first to see what can be achieved through PI.

I started to look out for Ideas at SDN forum and found some of my ex-colleagues (not one :smile: ) have implemented some sort of complex PDF handling in PI. Key take away for me here was iText.


iText is a very powerful open source library. Using it’s APIs we can work with PDFs/images in more way than I can count. This library exactly fitted requirement for my poc.

At SDN forum most of the suggestions are to create adapter module or JAVA mapping. Java programming is not best of my traits and I find it easy to work with UDF. Anyway I don’t have to create actual PDF file at source but to send it as base64 encoded string so UDF is best suited for this.

Scope: - PI will receive base64 encoded image as a string in payload. PI will merge these images and create a base64 encoded PDF. PI will put the base64 encoded PDF into a field in target payload which in turn will create xml file at target FTP.

Algorithm: - here I am explaining the basic algorithm.

  1. Read base64 encoded string from payload
  2. For each encode image:
    1. Decode the image
    2. Convert the image to PDF
    3. Add pdf to existing one.
  3. Convert PDF to base64 encoding
  4. Return string to payload.

Implementation:-

For this implementation itext jar “itextpdf-5.4.1.jar” has been used.

Import instructions:-

import com.itextpdf.text.Document;

import com.itextpdf.text.pdf.codec.Base64;

import com.itextpdf.text.*;

import com.itextpdf.text.Image;

import com.itextpdf.text.pdf.PdfWriter;

This is advanced UDF for type queue having one input of type string.  I have segregated the UDF code in multiple part for better understanding. I have also included the full version of UDF in last part of blog.

Part 1:Declarations:-

String merge = null; // store base64 encoded merged PDF document
Document pdfDoc = new Document();  //  Constructs a new Document with A4 page size
ByteArrayOutputStream output = new ByteArrayOutputStream(); // store pdf in byte array
PdfWriter writer = null;  // Constructs a PdfWriter
Image img = null;   // Constructs a PdfWriter


Part 2:Processing each encoded node:-

for(int i =0; i<encodedImgStr.length; i++)
{
.
// Code for merging images and creating PDF as described in part 3 and 4
.
}

Part 3:Decode the encoded image and read it into bytes:

String imgStr = encodedImgStr[i];
byte[] imgBytes = Base64.decode(imgStr);

Part 4:Convert images to PDF and merge:-

try{
             // get an instance of an image
                img = Image.getInstance(imgBytes);
            // get the plain height of the image
               float imgHeight = img.getPlainHeight() + 100; 
              // get the plain height of the image
                 float imgWidth = img.getPlainWidth() + 100; 
              // create the page for the document
               Rectangle pageSize = new Rectangle(imgWidth, imgHeight);
               // set the page size of the pdf
                 pdfDoc.setPageSize(pageSize);
   /* below code is executed only once. When first image is processed*/
                if(i ==0)
                {
   /*below method gets an instance of PdfWriter “writer”. pdfDoc  is the document that has to be written and output is the OutputStream the writer has to write which in this case is ByteArrayOutputStream. */
                      writer = PdfWriter.getInstance(pdfDoc, output);
                    writer.open();
pdfDoc.open();
                }
// Below method convert image to PDF. At each loop image is converted to pdf and new page is appended.
pdfDoc.add(img);
       }
catch (Exception e) {
}

Part 5:Close Document and Writer:-

// once document is written to output stream close the document and writer
pdfDoc.close();
writer.close();

Part 6:Convert output stream to byte:


// Create a new byte array pdfBytes and copy valid content of output stream output to pdfBytes.
byte [] pdfBytes = output.toByteArray ();

Part 7:Encode bytes to base64 encoding:-


// encode PDF bytes to base64.
merge = Base64.encodeBytes(pdfBytes);
// Add merged base64 encoded pdf to resultlist.
result.addValue(merge);

Below is the input message. Field “fileData” contains encoded images. For this POC I am not actually using “FileType”. I am using SOAP UI to test my interface.

I have used the same structure for output as well. Below is the output message.

I have written small code in NWDS using iText library to decode base64 string and create a PDF file.

Sample Code:-


import com.itextpdf.text.pdf.codec.*;
public class decodePDF {
            public static void main(String[] args) {
            // TODO Auto-generated method stub
               String file1 = "C:/Documents and Settings/Desktop/iText/PIencoded.txt";
               String file2 = "C:/Documents and Settings/Desktop/iText/PIadapter encoded2.pdf";
                Base64.decodeFileToFile(file1,file2);
      }
}

Full version of UDF mergeDoc UDF.

String merge = null;
Document pdfDoc = new Document();
ByteArrayOutputStream output = new ByteArrayOutputStream();
PdfWriter writer = null;
Image img = null;
        for(int i =0; i<encodedImgStr.length; i++)
     {
        String imgStr = encodedImgStr[i];
        byte[] imgBytes = Base64.decode(imgStr);
         try{
            img = Image.getInstance(imgBytes);
            float imgHeight = img.getPlainHeight() + 100; 
                  float imgWidth = img.getPlainWidth() + 100; 
                Rectangle pageSize = new Rectangle(imgWidth, imgHeight);
                pdfDoc.setPageSize(pageSize);
            if(i ==0)
            {
               writer = PdfWriter.getInstance(pdfDoc, output);
               writer.open();
                           pdfDoc.open();
                        }
                        pdfDoc.add(img);
                     }
                  catch (Exception e) {
                }
          }
pdfDoc.close();
writer.close();
byte [] pdfBytes = output.toByteArray ();
merge = Base64.encodeBytes(pdfBytes);
result.addValue(merge);

We can use iText library to achieve functionality like encryption, removing malicious codes, modify metadata etc. I am still exploring it and hope to find many interesting features we can use.

15 Comments
Labels in this area