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.
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:
- Get data from the fileUpload HTMLB page element
- Convert the content to XSTRING and insert into a folder
- 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
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:
- Determine a list of existing attachments for the particular object
- Display the list in HTML page for users and let them select a document to display
- 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.
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:
In this method we’ll have to do a couple of steps:
- Read selected document content and convert it to XSTRING
- 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>