Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
0 Kudos


Uploading/Downloading Files into/from SAP


Recently, I was faced with the task of implementing a file upload and download via a JSP application into and from the SAP Records Management. “Shouldn’t be big deal” I thought by myself assuming that I only have to plug together some predefined functions and everything will already be done. But this didn’t work out. I was faced with this task during 2005 on the basis of the SAP NetWeaver Developer Studio Version 2.0.11, a J2EE Engine with a kernel version 6.40, a SAP Financials and a SAP Dispute/Records-Management application whereas the last two applications could either resist on one SAP system or on two SAP systems embedded into an ALE scenario (this maybe considered to be old fashioned but such constellations still often occur amongst many SAP customers). If you perform a file upload via the SAP standard as of SAP NetWeaver Application Server Release 6.40 SP11 for the ABAP stack and SP13 for the Java stack even virus scans will be performed automatically via the following functions:



    • Function Module GUI_UPLOAD in the SAP ABAP Stack

    • HTTP_UPLOAD using Business Server Pages

    • FileUpload of the Web Dynpro for JAVA



But if you do something “exotic” like the development of native JSPs on top of the SAP J2EE Engine there are no predefined and standardized libraries or pluggable components which provide a suitable set of functions for uploading or downloading files. Therefore, there are several steps that must be carried out when implementing a JSP application which cannot use any of the previously mentioned SAP standard functions.



At first the GUI must provide an upload dialog. This can be achieved by the following steps:




    1. Usage of encryption type mulitpart/form-data.

    2. Creation of input fields of type file.

    3. Insertion of buttons or hyperlinks for either uploading files or removing uploaded files.



On the server side suitable classes have to handle such a request appropriately. For that purpose there is no SAP standard library that provides functions like




    1. parsing multipart/form-data requests,

    2. scanning files for virus infections,

    3. checking the mime types of the uploaded files against a set of allowed mime types,

    4. limiting the file size to an upper limit or

    5. limiting the number of concurrent uploads.



Considering the virus scan SAP provides the VSI (virus scan interface) which may be used to implement a virus scan. In http://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/docs/library/uuid/b00a87e5-0601-0010-87a7-9c04... you can find an official coding sample how the VSI can be integrated into your application but it only treats the VirusInfectionException. The following code snippet shows in more detail how this may be done:




<!codepublic void parseRequest(HttpServletRequest request, HttpServletResponse
<!code>                          response)
<!code>      throws IOException {
<!code>      …
<!code>            /*prepare for the virus scan */
<!code>            byte[] byteArrayToBeScanned = new byte[filesize];
<!code>            byte[] tmpByteArray;
<!code>            offset = 0;
<!code>            for (int l = 0; l < binaryFileContent.size(); l++)
<!code>            {
<!code>                   tmpByteArray = (byte[])binaryFileContent.get(l);
<!code>                   for (int j = 0; j < tmpByteArray.length; j++) {
<!code>                          byteArrayToBeScanned[offset + j] =
<!code>                                 tmpByteArray[j];
<!code>                   }
<!code>                   offset+=tmpByteArray.length;
<!code>            }
<!code>            /* Now the actual virus scan can be performed */
<!code>            Context ctx;
<!code>            try {
<!code>                   ctx = new InitialContext();
<!code>                   VSIService vsiService = (VSIService)
<!code>                          ctx.lookup(VSIService.JNDI_NAME);
<!code>                   if (vsiService != null) {
<!code>                          /* get a scan instance */
<!code>                          Instance myInstance = null;
<!code>                          try {
<!code>                                  myInstance = vsiService.getInstance();
<!code>                                 if(myInstance == null){               
<!code>                                 /*Virus Scanner is not configured log
<!code>                          this => VSIServiceException */
<!code>                                 }
<!code>                          myInstance.scanBytes
<!code>                          (filename,byteArrayToBeScanned,
<!code>                                 byteArrayToBeScanned.length);
<!code>                   /* if a virus is found =>                                    
<!code>                   VirusInfectionException    */


<!code>                   /* VirusInfectionException:
<!code>                                    file has a virus, logging
<!code>                                    entry to be created, handle this
<!code>                                     exception as a user error, throw away
<!code>                                        files to be uploaded */
<!code>                                 binaryFileContent = null;
<!code>                                 byteArrayToBeScanned = null;
<!code>                                 filesize = 0;
<!code>                                 /* user message to be send to
<!code>                          the GUI: "error.fileIsInfected" */
<!code>                          } catch (VirusScanException vse) {
<!code>                                 /* scan service has been
<!code>                                    installed but can not cope
<!code>                                    with the file to be scanned
<!code>                                    the file will be thrown away
<!code>                                 logging entry to be created  */
<!code>                                 binaryFileContent = null;
<!code>                                 byteArrayToBeScanned = null;
<!code>                                 filesize = 0;
<!code>                                 /* inform user that that virus
<!code>                                 scanner cannot say without any
<!code>                                 doubt  whether there aren't
<!code>                                 viruses inside the file
<!code>                                 "error.fileMightBeInfected"  */
<!code>                          } catch (VSIServiceException vse) {     
<!code>                             /*  VSIServiceException: the scan
<!code>                                 servicehasn't been fully
<!code>                                installed no user message
<!code>                                 logging entry keep file
<!code>                                 Perhaps the virus scan has
<!code>                                 already be done by the firewall
<!code>                                 and therefore the scan service
<!code>                                 hasn't been   installed
<!code>                                 "parseRequest",
<!code>                          "logmsg.virusScanNotActive",  */
<!code>                          } catch (Exception e) {
<!code>                                 /* catch all other Exceptions
<!code>                                  * expected error an log them
<!code>                                  * "error.uploadError",
<!code>                                  */
<!code>                                 binaryFileContent = null;
<!code>                                 byteArrayToBeScanned = null;
<!code>                                 filesize = 0;
<!code>                          } finally {
<!code>                                 /* release the scan instance */
<!code>                                 vsiService.releaseInstance
<!code>                                                      (myInstance);
<!code>                          }
<!code>                   }
<!code>            } catch (NamingException e) {
<!code>                   binaryFileContent = null;
<!code>                   byteArrayToBeScanned = null;
<!code>                   filesize = 0;
<!code>                   /* "error.uploadError", */
<!code>            }
<!code>           
<!code>  }
<!code>   


When the virus scan is implemented and the web application is deployed and running on the J2EE Server, the scanner has to be activated before it can perform virus scans. This means to use partner products to perform the actual virus scan and to configure the virus scan provider of the J2EE Engine, for instance by means of the Visual Administrator.



Having uploaded the files to the J2EE Engine they have to be sent into the SAP system. This can be done with the aid of the SAP Java Connector (JCO). For that purpose the files have to be converted from their binary format into the specific format of the JCO table which is a representation of a database table of the SAP system. The field for the file content of such a table could be of type RAW of the length 255. In this case length 255 has been chosen because this is the maximum length that is allowed for fields, which have to pass an ALE interface. Finally, to store the files in the SAP Records Management various functions are available. BAPI_SRM_DOC_CHECKIN_VIA_TAB is one of them. Since the field of the table for the file content is of length 1022 another conversion of the internal representation of the file has to be carried out, one additional source of errors. Since many BAPIs for checking in files do not perform an internal virus scan it becomes necessary to do this in advance as outlined previously.



Downloading a file utilizes the same techniques. A BAPI call via the JCO is triggered by clicking on a button or on a hyperlink on client side. The data is transferred from the SAP system into the memory of the J2EE engine and, assuming that the representation of such a file is of type RAW of length 1022 the browser specific download dialog could be triggered by the following servlet (jcotable denotes the corresponding table. Attachment is a utility class which stores the file content and some additional information. The file content and the additional information are attached to the http request as an attribute).




<!codepackage com.sap.example;
<!codeimport java.io.IOException;
<!codeimport java.io.OutputStream;
<!codeimport javax.servlet.ServletException;
<!codeimport javax.servlet.http.HttpServlet;
<!codeimport javax.servlet.http.HttpServletRequest;
<!codeimport javax.servlet.http.HttpServletResponse;
<!codeimport com.sap.mw.jco.JCO;
<!codeimport com.sap.example.Attachment;
<!codepublic class DisputeDisplayAttachment extends HttpServlet {
<!codepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
<!code>      int lastValidByteIndex = -1;
<!code>      int lastValidLine = -1;
<!code>      final String method = "doGet";
<!code>      OutputStream out = response.getOutputStream();
<!code>      Attachment da = (Attachment)                request.getAttribute(Constants.ATTACHMENT);
<!code>      String mimeType = da.getMimeType();
<!code>      int documentSize = da.getDocumentSize();
<!code>      JCO.Table jcotable = da.getBinaryContent();
<!code>      String documentName = da.getDocumentName();
<!code>      int numberOfRows = jcotable.getNumRows();
<!code>      lastValidByteIndex = documentSize%1022;
<!code>      lastValidLine = numberOfRows-1;
<!code>      if (lastValidByteIndex == -1) {
<!code>            /error/
<!code>            return;
<!code>      }
<!code>      response.setContentType(mimeType);
<!code>      response.setContentLength( documentSize );
<!code>      response.setHeader(
<!code>            "Content-Disposition",
<!code>            "attachment; filename=" + documentName);
<!code>      for (int i = 0; i < lastValidLine; i++) {
<!code>            jcotable.setRow(i);
<!code>            out.write(jcotable.getByteArray("LINE"));
<!code>            documentSize-=1022;
<!code>      }
<!code>      jcotable.setRow(lastValidLine);
<!code>      out.write(jcotable.getByteArray("LINE"), 0, documentSize);
<!code>      out.flush();
<!code>      out.close();
<!code>  }
<!codepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
<!code>      doGet(request, response);
<!code>  }
<!code>  }



Thus, concluding our considerations we can state that there are many possibilities to implement the upload and download of files. But if you do not want to be constrained to the ABAP Stack, to BSPs or to Web Dynpro there are many requirements which are not met by a predefined set of functions albeit the upload and download of files is a quite elementary requirement. This brings us immediately to a more general question, namely whether future releases of SAP NetWeaver will provide a mature and fully developed platform. We will see.


                                                                  
3 Comments
Top kudoed authors