Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 

Introduction:


I would like to explain about how to Attach File to ODATA . This blog Post is mainly useful for beginners.


Please follow the below steps to Create attachments.


Step: 1 Go to SEGW T-code and create new project.






Click on Create button .The Popup will open.





Step:2 Give the ‘Project name’ and ‘Description’ ‘Package’ and click on Continue.





Step:3 Right click on Data Model ->create->Entity Type and Give the Entity type name and check Create Default Entity set and click on ‘Continue’.





Step:4 The entity for attachments is to be marked as ‘Media Type’ .




Step: 5 Now Create properties for the above Entity Type and must Select the key for your structure  and Click on ‘Generate runtime objects‘ button and the message shows generated successfully as below.





Step: 6 Click on methods–>inherited–>Redefine and write the logic.





The model provider extension class should redefine DEFINE method to handle this Media Type entity.



METHOD define.

super->define( ).

DATA: lo_entity TYPE REF TO /iwbep/if_mgw_odata_entity_typ,
lo_entity1 TYPE REF TO /iwbep/if_mgw_odata_entity_typ,
lo_property TYPE REF TO /iwbep/if_mgw_odata_property.

lo_entity = model->get_entity_type( iv_entity_name = 'Attachment' ).

IF lo_entity IS BOUND.
lo_property = lo_entity->get_property( iv_property_name = 'Delivery' ).
lo_property = lo_entity->get_property( iv_property_name = 'Filename' ).
lo_property = lo_entity->get_property( iv_property_name = 'Mimetype' ).
lo_property = lo_entity->get_property( iv_property_name = 'Value' ).

lo_property->set_as_content_type( ).
ENDIF.

ENDMETHOD.


 

Data Provider


The three main methods GET_ENTITYSET (attachment list), GET_STREAM, CREATE_STREAM and implemented in a utility class which is expected to be reused from each service requiring object services attachments.

 

CREATE_STREAM


This method will upload the any types of files attachment.
   METHOD /iwbep/if_mgw_appl_srv_runtime~create_stream.
*--upload input attachments and saving in business content server for further process.
*--data declarations

DATA: lt_objhead TYPE STANDARD TABLE OF soli,
ls_objhead TYPE soli,
ls_object TYPE borident,
lt_xdata TYPE solix_tab,
ls_xdata TYPE soli,
lt_data TYPE soli_tab,
ls_folmem_k TYPE sofmk,
ls_note TYPE borident,
ls_obj_id TYPE soodk,
ls_fol_id TYPE soodk,
ls_obj_data TYPE sood1,
lv_ep_note TYPE borident-objkey,
lv_tmp_fn TYPE string,
lv_tmp_des TYPE string,
lv_offset TYPE i,
lv_size TYPE i,
lv_temp_len TYPE i,
lv_offset_old TYPE i,
lv_extension TYPE string,
lv_reqstring TYPE string,
lv_key TYPE swo_typeid,
lv_type TYPE swo_objtyp,
lv_task TYPE char4,
lo_message_container TYPE REF TO /iwbep/if_message_container,
lv_text TYPE bapiret2,
lv_corid TYPE string,
ls_data TYPE zcl_zattch_file_mpc=>ts_attachment.

CONSTANTS: lc_hex_null TYPE x LENGTH 1 VALUE '20'.

DATA(lv_xstring) = is_media_resource-value.
DATA(lv_mimetype) = is_media_resource-mime_type.

*--splitting input file name into file name and extension.
SPLIT iv_slug AT '/' INTO lv_corid lv_tmp_fn.
SPLIT lv_tmp_fn AT '.' INTO lv_tmp_fn lv_extension.


*--call function to convert xsrting to binary
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_xstring
append_to_table = 'X'
IMPORTING
output_length = lv_size
TABLES
binary_tab = lt_xdata.

*--change hex data to text data
CALL FUNCTION 'SO_SOLIXTAB_TO_SOLITAB'
EXPORTING
ip_solixtab = lt_xdata
IMPORTING
ep_solitab = lt_data.

*--call function to get folder id
CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
EXPORTING
region = 'B'
IMPORTING
folder_id = ls_fol_id
EXCEPTIONS
communication_failure = 1
owner_not_exist = 2
system_failure = 3
x_error = 4
OTHERS = 5.

IF sy-subrc = 0.
ls_obj_data-objsns = 'O'.
ls_obj_data-objla = sy-langu.
ls_obj_data-objdes = lv_tmp_fn.
ls_obj_data-file_ext = lv_extension.
ls_obj_data-objlen = lv_size.
TRANSLATE ls_obj_data-file_ext TO UPPER CASE.
TRANSLATE lv_tmp_fn TO UPPER CASE.

CONCATENATE lv_tmp_fn '.' lv_extension INTO lv_tmp_des.
TRANSLATE ls_obj_data-objdes TO UPPER CASE.
ls_objhead = lv_tmp_des.
APPEND ls_objhead TO lt_objhead.

*--insert document into business content server.

CALL FUNCTION 'SO_OBJECT_INSERT'
EXPORTING
folder_id = ls_fol_id
object_type = 'EXT'
object_hd_change = ls_obj_data
IMPORTING
object_id = ls_obj_id
TABLES
objhead = lt_objhead
objcont = lt_data
EXCEPTIONS
active_user_not_exist = 1
communication_failure = 2
component_not_available = 3
dl_name_exist = 4
folder_not_exist = 5
folder_no_authorization = 6
object_type_not_exist = 7
operation_no_authorization = 8
owner_not_exist = 9
parameter_error = 10
substitute_not_active = 11
substitute_not_defined = 12
system_failure = 13
x_error = 14
OTHERS = 15.
IF sy-subrc = 0 .
COMMIT WORK.
lv_key = lv_corid.
ls_object-objkey = lv_key.
ls_object-objtype = 'ZPC'.
ls_folmem_k-foltp = ls_fol_id-objtp.
ls_folmem_k-folyr = ls_fol_id-objyr.
ls_folmem_k-folno = ls_fol_id-objno.
ls_folmem_k-doctp = ls_obj_id-objtp.
ls_folmem_k-docyr = ls_obj_id-objyr.
ls_folmem_k-docno = ls_obj_id-objno.
lv_ep_note = ls_folmem_k.
ls_note-objkey = lv_ep_note.
ls_note-objtype = 'MESSAGE'.

CALL FUNCTION 'BINARY_RELATION_CREATE_COMMIT'
EXPORTING
obj_rolea = ls_object
obj_roleb = ls_note
relationtype = 'ATTA'
EXCEPTIONS
OTHERS = 1.

IF sy-subrc NE 0.
lv_text-message = 'Error during file upload'.
lo_message_container = /iwbep/if_mgw_conv_srv_runtime~get_message_container( ).
lo_message_container->add_message(
EXPORTING
iv_msg_type = 'E'
iv_msg_id = 'ZPC'
iv_msg_number = '000'
iv_msg_text = lv_text-message
).
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
textid = /iwbep/cx_mgw_busi_exception=>business_error
message_container = lo_message_container.

EXIT.
ELSE.
ls_data-delivery = lv_corid.
copy_data_to_ref( EXPORTING is_data = ls_data
CHANGING cr_data = er_entity ).


ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.

 

GET_STREAM


This method will display the content of attachment

 
METHOD /iwbep/if_mgw_appl_srv_runtime~get_stream.

DATA : ls_stream TYPE ty_s_media_resource,
ls_header TYPE ihttpnvp,
lv_docid TYPE sofolenti1-doc_id,
lt_objcon TYPE TABLE OF solisti1,
ls_text TYPE solisti1,
content_hex TYPE TABLE OF solix,
ls_content_hex TYPE solix,
lv_data TYPE xstring,
lv_xstring TYPE xstring,
lv_string TYPE string,
ls_doc_data TYPE sofolenti1,
lv_mimetype TYPE mimetypes-type,
lv_file_ext(5) TYPE c.

DATA: lv_name_utf8 TYPE string, "SAP Note 2076935
lv_filename_str TYPE string.

DATA: ls_docid_str TYPE soentryi1,
ls_filter TYPE sofor,
ls_folder TYPE sofdk,
ls_object TYPE soodk,
ls_obj_hd TYPE sood2,
lt_objhead TYPE STANDARD TABLE OF soli,
ls_objhead TYPE soli,
lv_filesize TYPE so_obj_len,
lt_split TYPE TABLE OF string,
lv_lines TYPE i,
ls_extension TYPE string,
lv_extension TYPE sdok_fnext,
ls_filename TYPE string,
lv_cor_value TYPE srgbtbrel-instid_a,
lv_file_te TYPE so_obj_des.

READ TABLE it_key_tab INTO DATA(ls_cor) INDEX 1.
IF sy-subrc = 0.
lv_cor_value = ls_cor-value.
ENDIF.
READ TABLE it_key_tab INTO DATA(ls_file) INDEX 2.
IF sy-subrc = 0.
lv_file_te = ls_file-value.
ENDIF.


IF lv_cor_value IS NOT INITIAL AND lv_file_te IS NOT INITIAL.
SELECT instid_b
FROM srgbtbrel INTO TABLE @DATA(lt_docid)
WHERE reltype = 'ATTA'
AND instid_a = @lv_cor_value
AND typeid_a = 'ZPC'.
ENDIF.

IF lt_docid IS NOT INITIAL.

LOOP AT lt_docid INTO DATA(ls_doc_id)
WHERE instid_b IS NOT INITIAL.

CLEAR: ls_stream, lv_docid,lt_objcon.
lv_docid = ls_doc_id-instid_b.

CALL FUNCTION 'SO_DOCUMENT_READ_API1'
EXPORTING
document_id = lv_docid
IMPORTING
document_data = ls_doc_data
TABLES
object_content = lt_objcon
contents_hex = content_hex
EXCEPTIONS
document_id_not_exist = 1
operation_no_authorization = 2
x_error = 3
OTHERS = 4.

IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.

IF ls_doc_data-obj_descr = lv_file_te.

ls_filter-sndi = abap_true.
MOVE lv_docid TO ls_docid_str.
MOVE-CORRESPONDING ls_docid_str TO ls_folder.
MOVE-CORRESPONDING ls_docid_str TO ls_object.

CALL FUNCTION 'SO_OBJECT_READ'
EXPORTING
filter = ls_filter
folder_id = ls_folder
object_id = ls_object
IMPORTING
object_hd_display = ls_obj_hd
TABLES
objhead = lt_objhead
EXCEPTIONS
active_user_not_exist = 1
communication_failure = 2
component_not_available = 3
folder_not_exist = 4
folder_no_authorization = 5
object_not_exist = 6
object_no_authorization = 7
operation_no_authorization = 8
owner_not_exist = 9
parameter_error = 10
substitute_not_active = 11
substitute_not_defined = 12
system_failure = 13
x_error = 14
OTHERS = 15.
IF sy-subrc <> 0.
RETURN.
ENDIF.
LOOP AT lt_objhead INTO ls_objhead
WHERE table_line CP '&SO_FILENAME=*'.
SPLIT ls_objhead AT '.' INTO TABLE lt_split.
IF sy-subrc IS INITIAL..
lv_lines = lines( lt_split ).
IF lv_lines <> 0.
READ TABLE lt_split INTO ls_extension INDEX lv_lines.
*
IF lv_extension <> ls_obj_hd-file_ext.
SELECT SINGLE type INTO lv_mimetype FROM sdokmime_c
WHERE extension = lv_extension.
IF sy-subrc <> 0.
SELECT SINGLE type INTO lv_mimetype FROM sdokmime
WHERE extension = lv_extension.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
EXIT.
ENDLOOP.

IF sy-subrc <> 0.
* common processing, calculate mime-type
CALL FUNCTION 'SDOK_MIMETYPE_GET'
EXPORTING
extension = ls_doc_data-obj_type
IMPORTING
mimetype = lv_mimetype.
ENDIF.


IF content_hex IS NOT INITIAL.
*
LOOP AT content_hex INTO ls_content_hex.
CONCATENATE lv_xstring ls_content_hex-line INTO lv_xstring IN BYTE MODE.
ENDLOOP.
* ---------------------------------------------------------------
* it turned out that the stream is too long; old applications
* (e.g. office 2003) just ignored that, the new ones (e.g. office
* 2010) fail in displaying that
* ---------------------------------------------------------------
MOVE lv_xstring(ls_doc_data-doc_size) TO lv_xstring.
ls_stream-value = lv_xstring.
ls_stream-mime_type = lv_mimetype.
*
ELSEIF lt_objcon IS NOT INITIAL.
*
CLEAR: lv_string.
LOOP AT lt_objcon INTO ls_text.
CONCATENATE lv_string ls_text-line cl_abap_char_utilities=>newline INTO lv_string.
ENDLOOP.
*
CALL FUNCTION 'HR_KR_STRING_TO_XSTRING'
EXPORTING
* CODEPAGE_TO = '8500'
unicode_string = lv_string
* OUT_LEN =
IMPORTING
xstring_stream = lv_xstring
EXCEPTIONS
invalid_codepage = 1
invalid_string = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ls_stream-value = lv_xstring.
ls_stream-mime_type = lv_mimetype.

ENDIF.
TRANSLATE ls_doc_data-obj_type TO LOWER CASE.
lv_file_ext = ls_doc_data-obj_type.

IF lv_mimetype IS INITIAL.

CALL FUNCTION 'SDOK_MIMETYPE_GET'
EXPORTING
extension = lv_file_ext
IMPORTING
mimetype = lv_mimetype.
ls_stream-mime_type = lv_mimetype.
ELSE.
ls_stream-mime_type = lv_mimetype.
ENDIF.

CONCATENATE ls_doc_data-obj_descr '.' lv_file_ext INTO ls_filename.
ls_header-name = 'Content-Disposition'.
IF ls_stream-mime_type NE 'application/pdf' .
lv_filename_str = ls_filename.
lv_name_utf8 = cl_http_utility=>if_http_utility~escape_url( unescaped = lv_filename_str ).
REPLACE ALL OCCURRENCES OF '%2e' IN lv_name_utf8 WITH '.'.
CONCATENATE 'attachment; filename*=UTF-8''''' lv_name_utf8 INTO ls_header-value.
set_header( is_header = ls_header ).
ENDIF.

EXIT.
ENDIF.
ENDLOOP.

copy_data_to_ref( EXPORTING is_data = ls_stream
CHANGING cr_data = er_stream ).

ENDIF.

ENDMETHOD.

 

GET_ENTITYSET


This method would retrieve the list of attachments for a business object.
  METHOD attachmentset_get_entityset.

**Data Declaration
DATA: ls_select_opt TYPE /iwbep/s_cod_select_option,
lr_corid TYPE RANGE OF CHAR10,
ls_entity TYPE zcl_zattch_file_mpc=>ts_attachment,
ls_doc_data TYPE sofolenti1,
lv_docid TYPE sofolenti1-doc_id,
lo_message_container TYPE REF TO /iwbep/if_message_container,
lv_text TYPE bapiret2.

**Get Filter Data
DATA(lt_filters) = io_tech_request_context->get_filter( )->get_filter_select_options( ).

**Prepare data from filter options
LOOP AT lt_filters ASSIGNING FIELD-SYMBOL(<ls_filter>).
CASE <ls_filter>-property.
WHEN 'DELIVERY'.
ls_select_opt = <ls_filter>-select_options[ 1 ].
IF sy-subrc = 0.
DATA(lv_corid) = ls_select_opt-low.
ENDIF.
ENDCASE.
ENDLOOP.

**Range tables for input data
IF lv_corid NE ''.
lr_corid = VALUE #( ( sign = 'I' option = 'EQ' low = lv_corid ) ).
ENDIF.


**Get Correction ID attachments

SELECT instid_a,
instid_b
FROM srgbtbrel INTO TABLE @DATA(lt_docs)
WHERE reltype = 'ATTA'
AND instid_a IN @lr_corid
AND typeid_a = 'ZPC'.

IF lt_docs IS NOT INITIAL.

LOOP AT lt_docs ASSIGNING FIELD-SYMBOL(<ls_doc>)
WHERE instid_b IS NOT INITIAL.

CLEAR: ls_doc_data,lv_docid.
lv_docid = <ls_doc>-instid_b.

CALL FUNCTION 'SO_DOCUMENT_READ_API1'
EXPORTING
document_id = lv_docid
IMPORTING
document_data = ls_doc_data
EXCEPTIONS
document_id_not_exist = 1
operation_no_authorization = 2
x_error = 3
OTHERS = 4.

IF sy-subrc <> 0.
CONTINUE.
ENDIF.

ls_entity-DELIVERY = <ls_doc>-instid_a.
ls_entity-filename = ls_doc_data-obj_descr.
ls_entity-mimetype = ls_doc_data-obj_type.
APPEND ls_entity TO et_entityset.
CLEAR:ls_entity.

ENDLOOP.
ENDIF.

ENDMETHOD.

 

Save and Activate the entity sets.

Step:11 Add and Maintain the service:

Go for the t-code ‘ /IWFND/MAINT_SERVICE‘ to add the service.

Click on ‘Add service‘ to add service.


 

Step:12  Give system name and click on ‘Get service‘ and the project will be found and select project click on ‘Add selected service‘. It will automatically maintained the service.


 

Step: 13  After it will shows technical service with some details and Click on Continue button.


Step: 14 Go back to maintain services and select the project and ‘Load Metadata‘ & Click on ‘Sap Gateway Client‘.


Step: 15 .It will shows the HTTP Request with Request URI and select the entity set name as below.


Click on Add Header Button and enter  Header name 'slug' and enter Header Value abc/Test.docx click on continue button.


Click on Add file and select file

Step:17  click on ‘POST‘ radio button for create.

(Status code: ‘201‘) as below.


 

Conclusion:    
I hope this blog Post helps to to attach multiple files with different file extensions via OData Service

Hope this useful to you. Thanks
2 Comments