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!
Showing results for 
Search instead for 
Did you mean: 
0 Kudos
Suppose business requirement is like:

  • Using SAP-PI web-service, read multiple .CSV files in to single Zip File and send it as an attachment to third Party

Then for such business requirement one sap-pi scenario can be created like:

  • Soap to File Inbound Synchronous Interface

  • that means one sap-pi soap web-service synchronous scenario where:

    1. in Response Message Mapping, one UDF will be required to Read files and set them as an zip attachment

    2. Scenario will have Communication Channels like Soap Sender and File Receiver

    3. File Receiver channel's job will be only to create a dummy empty file in SAP's app directory and that file will be overwritten for each time. This File channel is required only to complete scenario.

SAP PI UDF example which is "To Set multiple CSV file as an zip Attachment to Response Message Payload", will have below functionality :

  • To read multiple CSV files from folder

  • compress them to a single Zip file. Here limit 10 CSV files per zip

  • Archive each zipped CSV file to other directory

  • Set zip file as an attachment

  • Set Zip File name to Dynamic Configuration variable, so that same FileName can be used further

public String zipToAttachment(String filePath, String archivePath, Container container) 
throws StreamTransformationException{

UDF for below functionalities:
To get current Date time
To Read 10 files from a directory of SAP-APP server (only .CSV files and should not starts with "ARC")
To zip 10 files in a single zip file and rename zip as "zipFileName_currentDateTime"
To archive 10 files to other directory
To set single zip file as attachment to HTTP response message
To set attachment header as "application/zip"

//Start of :Get Current Date Time ............................................
//Current DateTime to be used in ZipFileNaming conventions
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd : HHmmssSSS");
Date date = new Date();
String cDate = dateFormat.format(date).toString();
cDate = cDate.replaceAll(" : ", "T");
//End of : Get Current Date Time .............................................

String Input_filePath = filePath;
String Archive_filePath = archivePath;
String Ouput_Zip = "zipFileName_" + cDate + ".zip";//
String resultStr = "";
Boolean csvFound = false;
String errorStr = "";

//Start of CsvFile Zipping and archinving to other folder ....................
File[] fileDir = new File(Input_filePath).listFiles();
if (fileDir.length > 0) {
FileOutputStream fos = new FileOutputStream(Ouput_Zip);
ZipOutputStream zos = new ZipOutputStream(fos);

int fileCount = 0;

//Read each file in th directory
for (int i=0; i<fileDir.length; i++){

String Input_fileName = fileDir[i].getName(); //Get FileName
String Input_fileName_Path = fileDir[i].getPath(); //Get FileName with PathName

//Each file should be ".CSV" and should not startswith "ARC"
if(Input_fileName.startsWith("ARC")) {
//do nothing
}else{ // if fileName is not starting with "ARC"
if (Input_fileName.lastIndexOf(".CSV") > -1){
csvFound = true; //Here CSV file found

//start: Csv file zipping in to single zip ---------------------------
File file = new File(Input_fileName_Path);
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());

byte[] bytes = new byte[1024];
int length;
while ((length = >= 0) {
zos.write(bytes, 0, length);
//End of Csv file zipping in to single zip ---------------------------

//start: File archival -----------------------------------------------
file.renameTo(new File(Archive_filePath + file.getName()));
//end: File archival ------------------------------------------------

//Read only 10 CSV files for one Zip
fileCount = fileCount + 1;
if (fileCount == 10){
break; //break the (for...loop) if fileCount reached 10
}// end of "if case for fileCount"

}// end of "if case for CSV file Check"
} // end of "else if case for ARC file Check"
}//end of "for loop case for FileDirectiry"

if(csvFound == false){
errorStr += " | " + "No .CSV file found in directory: " + Input_filePath ;
//if atleast one .CSV file found with "ARC" prefix, only then zip file gets created
//and only then it is requried to close ZipOutputStream 'zos' and FileOutputStream 'fos'

//start: set zip as an Attachment ------------------------------------
//Return Zip file as an attachment to Soap Response Message
InputStream zipIpStrm = new FileInputStream(Ouput_Zip);
byte[] buffer = new byte[0xFFFF];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int len; (len = != -1;){
baos.write(buffer, 0, len);

GlobalContainer gblCtnr = container.getGlobalContainer();
OutputAttachments opAtch = gblCtnr.getOutputAttachments();
Attachment Atch = opAtch.create(Ouput_Zip, "application/zip", baos.toByteArray());
//end: set zip as an Attachment -----------------------------------------


}//end of "if (fileDir.length > 0) {"
}catch(Exception e){
errorStr += " | " + e.getMessage();
//End of CsvFile Zipping and archinving to other folder ...................

if (errorStr == ""){
resultStr = Ouput_Zip; //set zipFileName to return string
resultStr = errorStr; //return error
return resultStr;

}//end of UDF Fn "zipToAttachment"


In, Soap Sender Communication Channel, we should have checked 'Keep attachments', only then this udf will return attachments with soap response message



Sending pdf file attachments into Soap-API's Request Field which is bound to receive attachments in ByteArray format.

For above case, we can use below UDF example and apply this UDF into respective Field map of GraphicalMapping:
* This UDF requires input as FilePath_fileName of pdf file which is residning in SAP-R3's All directory
* Functionality of UDF:
* 1. Pull the pdf file from SAP-R3's AL11 directory and archive it
* 2. set this file as an attachment to wbservice reqeust

//String prxIpFPathFName = "/sapFolder/xYFolder/Sample0026.PDF";
String resultStr = "";
String prxIp_FilePath = "";
String prxIp_FileName = "";
String Archive_filePath = "";
try {

if (prxIpFPathFName.indexOf("/") > -1) {
prxIpFPathFName.replaceAll("//", "/");
prxIp_FileName = prxIpFPathFName.substring(prxIpFPathFName.lastIndexOf("/") + 1);
prxIp_FilePath = prxIpFPathFName.substring(0, prxIpFPathFName.lastIndexOf("/") + 1);
Archive_filePath = prxIp_FilePath + "Archive/";

resultStr = prxIp_FileName;
if (prxIp_FileName.length() > 0) {

File[] fileDir = new File(prxIp_FilePath).listFiles();
if (fileDir.length > 0) {
for (int i = 0; i < fileDir.length; i++) { // Loop throughout each files in directory

String Input_fileName = fileDir[i].getName();
if (Input_fileName.lastIndexOf(prxIp_FileName) > -1) {

// start: set as Attachment -----------------------------------------------
File file = new File(prxIpFPathFName);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = != -1;) {
baos.write(buf, 0, readNum); //no doubt here is 0
} catch (Exception ex) {
byte[] bytes = baos.toByteArray();

//Convert byte[] to String
resultStr = Base64.getEncoder().encodeToString(bytes);

// end: set as Attachment ------------------------------------------------

// start: File archival ----------------------------------------------------
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd : HHmmssSSS");
Date date = new Date();
String cDate = dateFormat.format(date).toString();
cDate = cDate.replaceAll(" : ", "T");
String arcFNm = Archive_filePath + cDate + "_" + prxIp_FileName;
if(file.renameTo (new File(arcFNm))){
// end: File archival ----------------------------------------------------

} // end of for..loop of fileDir check
} catch (Exception e) {
resultStr += " Exception while setting attachment: " + e.getMessage();

return resultStr;



Labels in this area