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

Introduction


Ability to create and display file attachments in portal applications is important and very often requested by many clients. For instance: with ESS/MSS applications many clients want to be able to supplement a PCR requests with some additional information in a form of file attachments, or an employee requesting a life event adjustment wants to be able to attach scanned images of various supporting documents for HR; or in many other cases.
The functionality is so useful and natural to portal environment, yet is not too easy and obvious to implement.


This is why I decided to post this blog that shows how to do it in BSP applications and provides some simple code samples. These instructions focus on release 610 and up. All code samples are taken from a 610 system as well.


Create Attachment


We need to provide users with a way to select a file that they want to attach, and a way to tell system to go ahead and attach the selected file. You may want to create more sophisticated design, but for this demo I just displayed a file selection box and an ‘Attach’ button next to it on my page – it looks like on the picture below.


!http://webcaff.com/slabs/images/stories/bsp1/screen1.jpg|width=100%|src=http://webcaff.com/slabs/ima...!


There are two pieces of a puzzle that you’ll need to consider to insert this in your page:
    • - HTML code that puts the file selection box and an Attach Document; button on screen
    • - Event handler, which kicks off when users hit Attach Document; button and actually create the attachment from the selected file


HTML Code


The following HTML code was used to display the section You can attach additional documents here, which is shown on the screen shot above. It uses HTMLB fileUpload extension to handle the whole file selection dialog.


-
<htmlb:group id      = "group1"
             design  = "sapcolor"
             tooltip = "Document attachment" >
  <htmlb:groupHeader>
    <htmlb:textView text="You can attach additional documents here..." />
  </htmlb:groupHeader>
  <htmlb:groupBody>
    <htmlb:fileUpload id     = "DocUpload"
                      size   = "50"
                      accept = "true" />
    <htmlb:button id      = "Attach"
                  text    = "Attach Document"
                  onClick = "HandleUpload" />
  </htmlb:groupBody>
</htmlb:group>
-
</TEXTAREA>


Event Handler


I used MVC concept for the following code appears in DO_HANDLE_EVENT method in my controller. If you use simple Page with Flow Logic instead then you can insert it in OnInputProcessing section on Event Handler tab. Since the code is tuned for MVC you may need to make some changes to make it work with a flow logic pages.


Method: DO_HANDLE_EVENT


Event_server_name.


          when 'HandleUpload'.


            handleupload( ).


          when others.
. . .
</TEXTAREA>

Method: handleupload</h3>


In this method we’ll have to do a couple of steps:

    1. - Get data from the fileUpload HTMLB page element
    2. - Convert the content to XSTRING and insert into a folder
    3. - Create a binary link between the attached content and your business object (e.g. invoice, PCR request, etc.)



1. Get data from the fileUpload element


                                       ).
2. Convert content and insert into a folder



…. . .


  data: l_folid type soodk,
        l_folderid type SOOBJINFI1-OBJECT_ID,
        l_size type i,
        lt_content type table of SOLISTI1.
  DATA: ls_document_data type sodocchgi1.
  data: l_doctype type SOODK-OBJTP.
  data: l_docinfo type sofolenti1.


  data: lt_words type table of string,
        l_token type string.


  data: l_att_key type SWOTOBJID-OBJKEY.


  IF data IS NOT INITIAL.


    l_folid = 'FOL28000000000004'.


    • I put this for test purposes. You will need to add code to figure out which ** folder your attachments should go to


    l_folderid = l_folid.


    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        BUFFER          = data->file_content
        APPEND_TO_TABLE = 'X'
      IMPORTING
        OUTPUT_LENGTH   = l_size
      TABLES
        BINARY_TAB      = lt_content.


    data: lc_word(100).


    l_token = data->file_name.


    while l_token ca '\'.
      split l_token at '\' into lc_word l_token.
    endwhile.


    split l_token at '.' into lc_word l_doctype.


    ls_document_data-obj_name = 'ATTACHMENT'.
    ls_document_data-obj_descr = l_token.
    ls_document_data-obj_langu = sy-langu.
    ls_document_data-doc_size = l_size.
    ls_document_data-no_change = 'X'.


    CALL FUNCTION 'SO_DOCUMENT_INSERT_API1'
      EXPORTING
        folder_id                  = l_folderid
        document_data              = ls_document_data
        document_type              = l_doctype
      IMPORTING
        document_info              = l_docinfo
      TABLES
        object_content             = lt_content
  •        contents_hex                = lt_content
      EXCEPTIONS
        folder_not_exist           = 1
        document_type_not_exist    = 2
        operation_no_authorization = 3
        parameter_error            = 4
        x_error                    = 5
        enqueue_error              = 6
        OTHERS                     = 7.


    IF sy-subrc NE 0.
      MESSAGE e696(WL).
    ENDIF.


    l_att_key = l_docinfo-doc_id.


    . . .


  ENDIF.
. . .
</TEXTAREA>


3. Create a binary link


By creating a binary link we’re associating the uploaded attachment content with a particular SAP Business Object – so that it will be accessible with GOS and easier to find.
In this example I link it to a PCR object (BUS7051) – you can replace it with your own reference.


Display Attachment


To display attachment we’ll need to do the following:

    1. - Determine a list of existing attachments for the particular object
    2. - Display the list in HTML page for users and let them select a document to display
    3. - Display selected attachment in a proper format


Determine a list of existing attachments


If you have created a binary links before then it should be very easy to read existing attachments. All we have to do is to follow the links (literally).  A code sample below shows how to do this – all attachments are read into the LT_LINKS table which you can use to display the list in you HTML page.
READ_LINKS_OF_OBJECTS
        EXPORTING
          IT_OBJECTS          = lt_objects
          IP_LOGSYS           = ls_logsys
          IT_ROLE_OPTIONS     = lt_roles
          IT_RELATION_OPTIONS = lt_relopt
        IMPORTING
          ET_LINKS_A          = lt_links.
  •        ET_LINKS_B             =


    CATCH CX_OBL_MODEL_ERROR .
    CATCH CX_OBL_PARAMETER_ERROR .
    CATCH CX_OBL_INTERNAL_ERROR .
  ENDTRY.


. . .
</TEXTAREA>


Display List of Attachment in your HTML page


Since you already have a table with your attachments you can simply use a tableview element to display it.
A sample code below provides a little better display by showing a document type icon and displays the attachment names as clickable links. To display an attachment users will have to click on them.  Sample design is shown on a picture below:


Process user click and display a selected attachment


In the example above attachment names are displayed as clickable links and will generate a server event ‘on FileView’ when clicked.


As before, we’ll intercept user interaction in the DO_HANDLE_EVENT method:


Method: DO_HANDLE_EVENT


row_index.


            viewselection( rowselection ).


        endcase.
. . .
</TEXTAREA>


Method: viewselection


In this method we’ll have to do a couple of steps:

    1. - Read selected document content and convert it to XSTRING
    2. - Write content into an ICM cache to be displayed


1. Read and convert a document content


Document ID (L_docid) comes from the attachment table that we read before. Document content is read into LT_CONTENT table that will  be converted to XSTRING later. Finally we need to determine correct MIME type from the document extension.



. . .
  CALL FUNCTION 'SO_DOCUMENT_READ_API1'
    EXPORTING
      DOCUMENT_ID                      = l_docid
  •   FILTER                           = 'X '
   IMPORTING
     DOCUMENT_DATA                    = ls_docdata
   TABLES
  •   OBJECT_HEADER                    =
     OBJECT_CONTENT                   = lt_content
  •   OBJECT_PARA                      =
  •   OBJECT_PARB                      =
  •   ATTACHMENT_LIST                  =
  •   RECEIVER_LIST                    =
  •   CONTENTS_HEX                     =
   EXCEPTIONS
     DOCUMENT_ID_NOT_EXIST            = 1
     OPERATION_NO_AUTHORIZATION       = 2
     X_ERROR                          = 3
     OTHERS                           = 4
            .
  IF SY-SUBRC <> 0.
    MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.


  describe table lt_content lines l_size.
  multiply l_size by 255.


  CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
    EXPORTING
      INPUT_LENGTH       = l_size
  •   FIRST_LINE         = 0
  •   LAST_LINE          = 0
    IMPORTING
      BUFFER             = x_content
    TABLES
      BINARY_TAB         = lt_content
   EXCEPTIONS
     FAILED             = 1
     OTHERS             = 2
            .
  IF SY-SUBRC <> 0.
    MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.


  content = x_content.


  data: l_mimetype type W3CONTTYPE,
        l_type type string.


  translate ls_object-file_ext to lower case.


  clear l_type.


  CALL FUNCTION 'SDOK_MIMETYPE_GET'
    EXPORTING
      EXTENSION                  = ls_object-file_ext
      X_USE_LOCAL_REGISTRY       = 'X'
    IMPORTING
      MIMETYPE                   = l_mimetype
            .


  l_type = l_mimetype.

</TEXTAREA>


2. Write content into an ICM cache




3. Display document in a browser window


The last step is to place the document into the ICM cache.
With the above coding, we successfully created a new HTTP response in the ICM cache that can be addressed under the URL stored in "display_url" (page attribute of type STRING). The last step is to change the rendered HTML coding to also display the uploaded document. For this we just use an <iframe>.  The following HTML sequence is added in the layout, just before the end of the page.

<TEXTAREA NAME="createatt" COLS=80 ROWS=7 READONLY>
. . .
<%  IF pe->display_url IS NOT INITIAL.
      %>
      <script language="Javascript">
        window.open("<%= pe->display_url%>").focus();
      </script>
      <%
  ENDIF.
%>
. . .
</TEXTAREA>
4 Comments