cancel
Showing results for 
Search instead for 
Did you mean: 

PI Base64 Content to File Adapter

Former Member
0 Kudos

Hi!

I have the following Scenario and would like to solve it with SAP PI!

In R/3 backend, a Report reads a binary PDF File and converts the file into Base64. Then a FM is called which consists of a changing Parameter which holds the Base64 Content. The FM is called with target PI. PI should now DE-code this Base64 Content and save the Content as a binary file to disk! Simply said, i want to choose a PDF File within a Report which should be transferred to PI via Base64 Encoding and then saved to disk in it's original form ... I could already create the Report and the function module. But, my Problem is, how to create a mapping that ONLY takes the Base64 Content and writes this Content via File Adapter to disk!? Every mapping consists of additional XML fields, but in my case, only the source BASE64 Content should be saved to disk and NOT the fields which eventually could be in the target mapping structure!

Does anybody have an idea?

BR, EF

Accepted Solutions (0)

Answers (3)

Answers (3)

engswee
Active Contributor
0 Kudos

Hi Elmar

Here is an alternative you can consider. The following is a custom adapter module that can handle extracting the Base64 encoded string from an XML document based on XPath, and decode it. It is ready to deploy if you are on at least PI 7.31 SP13 or PI 7.4 SP08.

You can use this on the receiver FTP channel to process the XML message that came from the RFC sender.

I noticed that your RFC XML structure contains a filename field, if you need the target PDF to be dynamically named, you can add a message mapping in your scenario - just do a 1-1 mapping with the RFC XML as the source and target, and set the filename using Dynamic Configuration via a UDF.

If you need further details regarding this approach, feel free to ask.

Rgds

Eng Swee

RafaelVieira
Active Participant
0 Kudos

This message was moderated.

former_member181985
Active Contributor
0 Kudos

Hi Elmar,

Please go through my step by step wiki: http://wiki.scn.sap.com/wiki/display/XI/How+to+Send+Binary+Data+to+RFC+from+XI(or)PI?original_fqdn=w...

You just have to do it in reverse way i.e., from R/3 to PI to File

You can also avoid java mapping with below procedure if your pi version >= 7.1

  1. Use a message mapping between RFC structure and file structure (The file structure can just have a root node without any fields)
  2. Create UDF: which takes RFC base64 field as input, decodes base64 data to binary data and then create a binary pdf attachment with a relevant content ID as xxxxxx.pdf
  3. Use standard payloadswapbean to replace main payload with pdf attachment in receiver file channel configuration

That's all

BR,

Praveen Gujjeti

Former Member
0 Kudos

Hi!

At the moment i try this coding directly in the Attributes and Methods section ... my mapping looks like this. The FM delivers BASE64 encoded content in the BASE_64 field and the filename in the FNAME field. What i want, is to decode the BASE_64 content and make a file out of it! So, there should not be any target structure, but instead a single binary file as the output!

The problem now is, that i only get a 1kB file in size, which is of course not correct! How does the java mapping know, that i only want to decode the BASE_64 contents and NOT the whole stream?

Coding:

public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException {

         Map param = (Map) in.getInputHeader().getAll();

              param.put(DynamicConfigurationKey.create("http://sap.com/xi/XI/Dynamic", StreamTransformationConstants.DYNAMIC_CONFIGURATION), "");

         DynamicConfiguration conf = (DynamicConfiguration) param.get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

         DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File", "FileName");

            conf.put(key, "output.pdf");

try{

       InputStream is = in.getInputPayload().getInputStream();

            byte currentXMLBytes[] = is.toString().getBytes();

            ByteArrayInputStream bais = new ByteArrayInputStream(currentXMLBytes);

           

       /* byte[] array = new byte[bais.available()];

            bais.read(array); */

          ByteArrayOutputStream baos = new ByteArrayOutputStream();

            baos.write(BASE64Decoder.decode(currentXMLBytes));

        out.getOutputPayload().getOutputStream().write(baos.toByteArray());

          out.getOutputPayload().getOutputStream().flush();

} catch(Exception e) {}

}

former_member181985
Active Contributor
0 Kudos

Hi Elmar,

You can use normal java string api to fetch the content between tags <BASE64> and </BASE64> and then consider for decoding

My recommendation is to use a message mapping and form attachment as I have explaine 1,2 and 3 steps in my last reply

Best Regards,

Praveen Gujjeti

Former Member
0 Kudos

Hi Elmar,

did you get a solution for that problem?

Best

Mathias

former_member189420
Active Participant
0 Kudos

Hi Elmar,

I could think of 2 ways in solving this.

1. Use java mapping to receive a message in Base64Encoded form and Decode it in the mapping and write it to the OutputStream in Binary.

2.

     a. Use an UDF to decode the the Base64Encoded Payload and write it to the disk from the UDF.

     b. Return an empty string to map to the target dummy single element structure.

     c. Use Post processing OS command to delete the file written using the Receiver File               Communication Channel.

Hope it helps!

Cheers,

Anand Patil

Former Member
0 Kudos

Hello!

Option 1 Looks fine But, my Problem is, what happens after the outputStream? And what does the graphical mapping have to look like? A Java mapping function is represented as a new block in the graphical mapping, so what i have is the source --> the new mapping block --> the target .... but, i don't want to have the decoded base64 data inside an XML field, but instead, directly written to a file! Is this possible with Java mapping AND the graphical mapping somehow?

This is important, because my end-Scenario will use the file Adapter for FTP!! So, the decoded file should be uploaded by ftp ...

BR, EF

former_member189420
Active Participant
0 Kudos

Hi Elmar,

Yes it is possible using Java Mapping only. In that case you don't use the "blocks" but pure java mapping. Which will not be encapsulated within any XML structure. If you write to OutputStream in the java mapping it should work fine.

If you have to download the decoded payload to a disk and send to FTP in concurrence then you can as well write to the disk within Java Mapping directly.

Cheers,

Anand Patil

Former Member
0 Kudos

Hi!

Thank you for the informative hints on this I could successfully create the JAVA Mapping, respectively, i could compile it, without Errors! But can you give me some Information on how the necessary objects have to look like? I created a Mapping with source is FM Z_XXX and target Z_XXX. Here, no graphical mapping takes place, only source and target were defined. Then i created an Operation mapping where source is again Z_XXX and target is Z_XXX again. Here, i put in the mapping which i created! Is there anything else to do, now? How does the whole Thing work?

BR, EF