File uploads let you add file handling functionality to your applications inside the framework of SAP’s Rapid Application Programming (RAP) methodology. This gives customers the ability to upload a variety of file formats, including photos, Excel spreadsheets, PDFs, and more.
SAP’s Rapid Application Programming (RAP) architecture allows you to integrate file handling functionality into your applications through file uploads. Users can now upload a variety of file kinds, including PDFs, Excel spreadsheets, photos, and more.
OData streams are now supported by the RAP framework thanks to the most recent release of SAP BTP ABAP 2208. You may now make your RAP application capable of handling and maintaining Large Objects (LOBs).This feature enables media handling by giving end users the ability to upload external files in a variety of file formats, including PDF, XLSX, binary, and others.
In this Blog we will explore how to upload and handle Large Object such as PDF or Binary files without the need to extend the RAP application in BAS.
Large objects are modelled by means of the following fields:
Attachment Mime type Filename
The field Attachment contains the LOB itself in a RAWSTRING format and is technically bound to the field Mime type and Filename using semantics annotation.
Mime type represents the content type of the attachment uploaded and the values for the fields Mime type and Filename are derived from the field Attachment by the RAP framework based on the maintained CDS annotations. No attachment can exist without its mime type and vice versa.
For example, when a TEXT file is uploaded the Mime type field will be derived and populated with ‘APPLICATION/txt’.
Step 1 : Create the data element of raw string Datatype for the field that stores the file attachment in the Table.
Step 2 : Creating the Database table using below fields.
Step 3 : Create the Interface view on Above Database table.
@Semantics.mimeType: true => Use the above annotations to Handle the field as Mime Type by Internal Framework and to store the attached file which is usually large data. @Semantics.largeObject : { mime Type: ‘mime type’, file Name: ‘filename’, content Disposition Preference: #ATTACHMENT } => In this annotations we have to pass the mime type field name and the field which stores the file name.
Step 4 : Create the Projection View on Interface View.
Step 5 : Create the meta data extension for the created consumption view.
Step 6 : create the behavior definition for Interface View and choose the Implementation type as Unmanaged. For Media handling it is mandatory to create the OData v4 and with Draft functionality.
Draft table for the persistent Table.
Step 7 : Create the Implementation class for the behavior definition for CRUD operation.
CLASS lhc_zr_sm_t_file_hand DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR zr_sm_t_file_hand RESULT result.
METHODS create FOR MODIFY
IMPORTING entities FOR CREATE zr_sm_t_file_hand.
METHODS update FOR MODIFY
IMPORTING entities FOR UPDATE zr_sm_t_file_hand.
METHODS delete FOR MODIFY
IMPORTING keys FOR DELETE zr_sm_t_file_hand.
METHODS read FOR READ
IMPORTING keys FOR READ zr_sm_t_file_hand RESULT result.
METHODS lock FOR LOCK
IMPORTING keys FOR LOCK zr_sm_t_file_hand.
ENDCLASS.
CLASS lhc_zr_sm_t_file_hand IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD create.
zcl_sm_unmanaged_crud=>get_instance( )->create(
EXPORTING
entities = entities
CHANGING
mapped = mapped
failed = failed
reported = reported
).
ENDMETHOD.
METHOD update.
zcl_sm_unmanaged_crud=>get_instance( )->update(
EXPORTING
entities = entities
CHANGING
mapped = mapped
failed = failed
reported = reported
).
ENDMETHOD.
METHOD delete.
CALL METHOD zcl_sm_unmanaged_crud=>get_instance( )->delete(
EXPORTING
keys = keys
CHANGING
mapped = mapped
failed = failed
reported = reported
).
ENDMETHOD.
METHOD read.
zcl_sm_unmanaged_crud=>get_instance( )->read(
EXPORTING
keys = keys
CHANGING
result = result
failed = failed
reported = reported
).
ENDMETHOD.
METHOD lock.
ENDMETHOD.
ENDCLASS.
CLASS lsc_ZR_SM_T_FILE_HAND DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS finalize REDEFINITION.
METHODS check_before_save REDEFINITION.
METHODS save REDEFINITION.
METHODS cleanup REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_ZR_SM_T_FILE_HAND IMPLEMENTATION.
METHOD finalize.
ENDMETHOD.
METHOD check_before_save.
ENDMETHOD.
METHOD save.
zcl_sm_unmanaged_crud=>get_instance( )->save_data(
CHANGING
reported = reported
).
ENDMETHOD.
METHOD cleanup.
ENDMETHOD.
METHOD cleanup_finalize.
ENDMETHOD.
ENDCLASS.
Step 8 : Create the API class for the Implementation class.
CLASS zcl_sm_unmanaged_crud DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES: tt_std_create TYPE TABLE FOR CREATE zr_sm_t_file_hand,
tt_std_update TYPE TABLE FOR UPDATE zr_sm_t_file_hand,
tt_mapped_early TYPE RESPONSE FOR MAPPED EARLY zr_sm_t_file_hand,
tt_failed_early TYPE RESPONSE FOR FAILED EARLY zr_sm_t_file_hand,
tt_reported_early TYPE RESPONSE FOR REPORTED EARLY zr_sm_t_file_hand,
tt_mapped_late TYPE RESPONSE FOR MAPPED LATE zr_sm_t_file_hand,
tt_reported_late TYPE RESPONSE FOR REPORTED LATE zr_sm_t_file_hand,
tt_keys_read TYPE TABLE FOR READ IMPORT zr_sm_t_file_hand,
tt_keys_delete TYPE TABLE FOR DELETE zr_sm_t_file_hand,
tt_read_result TYPE TABLE FOR READ RESULT zr_sm_t_file_hand.
CLASS-METHODS get_instance RETURNING VALUE(ret_student) TYPE REF TO zcl_sm_unmanaged_crud.
METHODS: create IMPORTING entities TYPE tt_std_create
CHANGING mapped TYPE tt_mapped_early
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
read IMPORTING keys TYPE tt_keys_read
CHANGING result TYPE tt_read_result
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
update IMPORTING entities TYPE tt_std_update
CHANGING mapped TYPE tt_mapped_early
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
delete IMPORTING keys TYPE tt_keys_delete
CHANGING mapped TYPE tt_mapped_early
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
save_data CHANGING reported TYPE tt_reported_late.
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-DATA: go_instance TYPE REF TO zcl_sm_unmanaged_crud,
gt_create TYPE TABLE OF zsm_t_file_hand,
gt_update TYPE TABLE OF zsm_t_file_hand,
gr_delete TYPE RANGE OF zr_sm_t_file_hand-DocumentId,
gs_file TYPE zsm_t_file_hand.
ENDCLASS.
CLASS zcl_sm_unmanaged_crud IMPLEMENTATION.
METHOD get_instance.
ret_student = COND #( WHEN go_instance IS BOUND THEN go_instance
ELSE NEW #( ) ).
ENDMETHOD.
METHOD create.
gt_create = CORRESPONDING #( entities MAPPING FROM ENTITY ).
LOOP AT entities ASSIGNING FIELD-SYMBOL(<lfs_entities>).
IF gt_create IS NOT INITIAL.
gt_create[ 1 ]-client = sy-mandt.
gt_create[ 1 ]-last_changed_by = sy-uname.
GET TIME STAMP FIELD DATA(lv_timestamp).
gt_create[ 1 ]-last_changed_at = lv_timestamp.
mapped-zr_sm_t_file_hand = VALUE #( ( %cid = <lfs_entities>-%cid
%key = <lfs_entities>-%key
%is_draft = <lfs_entities>-%is_draft ) ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD save_data.
IF gt_create IS NOT INITIAL.
INSERT zsm_t_file_hand FROM TABLE _create.
CLEAR gt_create[].
ELSEIF gt_update IS NOT INITIAL.
UPDATE zsm_t_file_hand FROM TABLE _update.
CLEAR gt_update[].
ELSEIF gr_delete IS NOT INITIAL.
DELETE FROM zsm_t_file_hand WHERE document_id IN _delete.
CLEAR gr_delete[].
ENDIF.
ENDMETHOD.
METHOD update.
DATA : lt_update_x TYPE STANDARD TABLE OF zsm_ts_boolean,
lt_update TYPE STANDARD TABLE OF zsm_t_file_hand.
lt_update = CORRESPONDING #( entities MAPPING FROM ENTITY ).
lt_update_x = CORRESPONDING #( entities MAPPING FROM ENTITY USING CONTROL ).
IF lt_update IS NOT INITIAL.
*
SELECT * FROM zsm_t_file_hand FOR ALL ENTRIES IN _update
WHERE document_id = _update-document_id
INTO TABLE (lt_result_old).
ENDIF.
GET TIME STAMP FIELD DATA(lv_timestamp).
gt_update = VALUE #(
FOR x = 1 WHILE x LE lines( lt_update )
LET ls_control_flag = VALUE #( lt_update_x[ x ] OPTIONAL )
ls_new = VALUE #( lt_update[ x ] OPTIONAL )
ls_old = VALUE #( lt_result_old[ document_id = ls_new-document_id ] OPTIONAL )
IN
(
client = sy-mandt
document_id = COND #( WHEN ls_control_flag-document_id IS INITIAL
THEN ls_old-document_id )
filename = COND #( WHEN ls_control_flag-filename IS NOT INITIAL
THEN ls_new-filename ELSE ls_old-filename )
attachment = COND #( WHEN ls_control_flag-attachment IS NOT INITIAL
THEN ls_new-attachment ELSE ls_old-attachment )
mimetype = COND #( WHEN ls_control_flag-mimetype IS NOT INITIAL
THEN ls_new-mimetype ELSE ls_old-mimetype )
created_at = COND #( WHEN ls_control_flag-created_at IS INITIAL
THEN ls_old-created_at )
created_by = COND #( WHEN ls_control_flag-created_by IS INITIAL
THEN ls_old-created_by )
last_changed_at = COND #( WHEN ls_control_flag-last_changed_at IS INITIAL
THEN lv_timestamp )
last_changed_by = COND #( WHEN ls_control_flag-last_changed_by IS INITIAL
THEN sy-uname )
) ).
ENDMETHOD.
METHOD read.
SELECT * FROM zsm_t_file_hand FOR ALL ENTRIES IN
WHERE document_id = -DocumentId
INTO TABLE (lt_result).
result = CORRESPONDING #( lt_result MAPPING TO ENTITY ).
ENDMETHOD.
METHOD delete.
DATA: lt_delete TYPE STANDARD TABLE OF zsm_t_file_hand.
lt_delete = CORRESPONDING #( keys MAPPING FROM ENTITY ).
gr_delete = VALUE #(
FOR ls_delete IN lt_delete
sign = ‘I’ option = ‘EQ’ ( low = ls_delete-document_id )
).
ENDMETHOD.
ENDCLASS.
Step 7 : create the behavior definition for the Projection View.
Step 8 : Create the Service definition for the consumption view.
Step 9 : Create the Service Binding for Created Service definition and Choose the Binding type as OData V4 ,activate and publish the service.
Preview the Application and click on create to upload the file.
Click on upload icon near to the attachment field, select the file, file name will be auto filled and fill the Mime type manually.
File uploads let you add file handling functionality to your applications inside the framework of SAP’s Rapid Application Programming (RAP) methodology. This gives customers the ability to upload a variety of file formats, including photos, Excel spreadsheets, PDFs, and more.SAP’s Rapid Application Programming (RAP) architecture allows you to integrate file handling functionality into your applications through file uploads. Users can now upload a variety of file kinds, including PDFs, Excel spreadsheets, photos, and more.OData streams are now supported by the RAP framework thanks to the most recent release of SAP BTP ABAP 2208. You may now make your RAP application capable of handling and maintaining Large Objects (LOBs).This feature enables media handling by giving end users the ability to upload external files in a variety of file formats, including PDF, XLSX, binary, and others.In this Blog we will explore how to upload and handle Large Object such as PDF or Binary files without the need to extend the RAP application in BAS.Large objects are modelled by means of the following fields: Attachment Mime type Filename The field Attachment contains the LOB itself in a RAWSTRING format and is technically bound to the field Mime type and Filename using semantics annotation.Mime type represents the content type of the attachment uploaded and the values for the fields Mime type and Filename are derived from the field Attachment by the RAP framework based on the maintained CDS annotations. No attachment can exist without its mime type and vice versa.For example, when a TEXT file is uploaded the Mime type field will be derived and populated with ‘APPLICATION/txt’.Step 1 : Create the data element of raw string Datatype for the field that stores the file attachment in the Table.Step 2 : Creating the Database table using below fields.Step 3 : Create the Interface view on Above Database table.@Semantics.mimeType: true => Use the above annotations to Handle the field as Mime Type by Internal Framework and to store the attached file which is usually large data. @Semantics.largeObject : { mime Type: ‘mime type’, file Name: ‘filename’, content Disposition Preference: #ATTACHMENT } => In this annotations we have to pass the mime type field name and the field which stores the file name.Step 4 : Create the Projection View on Interface View.Step 5 : Create the meta data extension for the created consumption view.Step 6 : create the behavior definition for Interface View and choose the Implementation type as Unmanaged. For Media handling it is mandatory to create the OData v4 and with Draft functionality. Draft table for the persistent Table.Step 7 : Create the Implementation class for the behavior definition for CRUD operation. CLASS lhc_zr_sm_t_file_hand DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR zr_sm_t_file_hand RESULT result.
METHODS create FOR MODIFY
IMPORTING entities FOR CREATE zr_sm_t_file_hand.
METHODS update FOR MODIFY
IMPORTING entities FOR UPDATE zr_sm_t_file_hand.
METHODS delete FOR MODIFY
IMPORTING keys FOR DELETE zr_sm_t_file_hand.
METHODS read FOR READ
IMPORTING keys FOR READ zr_sm_t_file_hand RESULT result.
METHODS lock FOR LOCK
IMPORTING keys FOR LOCK zr_sm_t_file_hand.
ENDCLASS.
CLASS lhc_zr_sm_t_file_hand IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD create.
zcl_sm_unmanaged_crud=>get_instance( )->create(
EXPORTING
entities = entities
CHANGING
mapped = mapped
failed = failed
reported = reported
).
ENDMETHOD.
METHOD update.
zcl_sm_unmanaged_crud=>get_instance( )->update(
EXPORTING
entities = entities
CHANGING
mapped = mapped
failed = failed
reported = reported
).
ENDMETHOD.
METHOD delete.
CALL METHOD zcl_sm_unmanaged_crud=>get_instance( )->delete(
EXPORTING
keys = keys
CHANGING
mapped = mapped
failed = failed
reported = reported
).
ENDMETHOD.
METHOD read.
zcl_sm_unmanaged_crud=>get_instance( )->read(
EXPORTING
keys = keys
CHANGING
result = result
failed = failed
reported = reported
).
ENDMETHOD.
METHOD lock.
ENDMETHOD.
ENDCLASS.
CLASS lsc_ZR_SM_T_FILE_HAND DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS finalize REDEFINITION.
METHODS check_before_save REDEFINITION.
METHODS save REDEFINITION.
METHODS cleanup REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_ZR_SM_T_FILE_HAND IMPLEMENTATION.
METHOD finalize.
ENDMETHOD.
METHOD check_before_save.
ENDMETHOD.
METHOD save.
zcl_sm_unmanaged_crud=>get_instance( )->save_data(
CHANGING
reported = reported
).
ENDMETHOD.
METHOD cleanup.
ENDMETHOD.
METHOD cleanup_finalize.
ENDMETHOD.
ENDCLASS. Step 8 : Create the API class for the Implementation class. CLASS zcl_sm_unmanaged_crud DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES: tt_std_create TYPE TABLE FOR CREATE zr_sm_t_file_hand,
tt_std_update TYPE TABLE FOR UPDATE zr_sm_t_file_hand,
tt_mapped_early TYPE RESPONSE FOR MAPPED EARLY zr_sm_t_file_hand,
tt_failed_early TYPE RESPONSE FOR FAILED EARLY zr_sm_t_file_hand,
tt_reported_early TYPE RESPONSE FOR REPORTED EARLY zr_sm_t_file_hand,
tt_mapped_late TYPE RESPONSE FOR MAPPED LATE zr_sm_t_file_hand,
tt_reported_late TYPE RESPONSE FOR REPORTED LATE zr_sm_t_file_hand,
tt_keys_read TYPE TABLE FOR READ IMPORT zr_sm_t_file_hand,
tt_keys_delete TYPE TABLE FOR DELETE zr_sm_t_file_hand,
tt_read_result TYPE TABLE FOR READ RESULT zr_sm_t_file_hand.
CLASS-METHODS get_instance RETURNING VALUE(ret_student) TYPE REF TO zcl_sm_unmanaged_crud.
METHODS: create IMPORTING entities TYPE tt_std_create
CHANGING mapped TYPE tt_mapped_early
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
read IMPORTING keys TYPE tt_keys_read
CHANGING result TYPE tt_read_result
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
update IMPORTING entities TYPE tt_std_update
CHANGING mapped TYPE tt_mapped_early
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
delete IMPORTING keys TYPE tt_keys_delete
CHANGING mapped TYPE tt_mapped_early
failed TYPE tt_failed_early
reported TYPE tt_reported_early,
save_data CHANGING reported TYPE tt_reported_late.
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-DATA: go_instance TYPE REF TO zcl_sm_unmanaged_crud,
gt_create TYPE TABLE OF zsm_t_file_hand,
gt_update TYPE TABLE OF zsm_t_file_hand,
gr_delete TYPE RANGE OF zr_sm_t_file_hand-DocumentId,
gs_file TYPE zsm_t_file_hand.
ENDCLASS.
CLASS zcl_sm_unmanaged_crud IMPLEMENTATION.
METHOD get_instance.
ret_student = COND #( WHEN go_instance IS BOUND THEN go_instance
ELSE NEW #( ) ).
ENDMETHOD.
METHOD create.
gt_create = CORRESPONDING #( entities MAPPING FROM ENTITY ).
LOOP AT entities ASSIGNING FIELD-SYMBOL(<lfs_entities>).
IF gt_create IS NOT INITIAL.
gt_create[ 1 ]-client = sy-mandt.
gt_create[ 1 ]-last_changed_by = sy-uname.
GET TIME STAMP FIELD DATA(lv_timestamp).
gt_create[ 1 ]-last_changed_at = lv_timestamp.
mapped-zr_sm_t_file_hand = VALUE #( ( %cid = <lfs_entities>-%cid
%key = <lfs_entities>-%key
%is_draft = <lfs_entities>-%is_draft ) ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD save_data.
IF gt_create IS NOT INITIAL.
INSERT zsm_t_file_hand FROM TABLE _create.
CLEAR gt_create[].
ELSEIF gt_update IS NOT INITIAL.
UPDATE zsm_t_file_hand FROM TABLE _update.
CLEAR gt_update[].
ELSEIF gr_delete IS NOT INITIAL.
DELETE FROM zsm_t_file_hand WHERE document_id IN _delete.
CLEAR gr_delete[].
ENDIF.
ENDMETHOD.
METHOD update.
DATA : lt_update_x TYPE STANDARD TABLE OF zsm_ts_boolean,
lt_update TYPE STANDARD TABLE OF zsm_t_file_hand.
lt_update = CORRESPONDING #( entities MAPPING FROM ENTITY ).
lt_update_x = CORRESPONDING #( entities MAPPING FROM ENTITY USING CONTROL ).
IF lt_update IS NOT INITIAL.
*
SELECT * FROM zsm_t_file_hand FOR ALL ENTRIES IN _update
WHERE document_id = _update-document_id
INTO TABLE (lt_result_old).
ENDIF.
GET TIME STAMP FIELD DATA(lv_timestamp).
gt_update = VALUE #(
FOR x = 1 WHILE x LE lines( lt_update )
LET ls_control_flag = VALUE #( lt_update_x[ x ] OPTIONAL )
ls_new = VALUE #( lt_update[ x ] OPTIONAL )
ls_old = VALUE #( lt_result_old[ document_id = ls_new-document_id ] OPTIONAL )
IN
(
client = sy-mandt
document_id = COND #( WHEN ls_control_flag-document_id IS INITIAL
THEN ls_old-document_id )
filename = COND #( WHEN ls_control_flag-filename IS NOT INITIAL
THEN ls_new-filename ELSE ls_old-filename )
attachment = COND #( WHEN ls_control_flag-attachment IS NOT INITIAL
THEN ls_new-attachment ELSE ls_old-attachment )
mimetype = COND #( WHEN ls_control_flag-mimetype IS NOT INITIAL
THEN ls_new-mimetype ELSE ls_old-mimetype )
created_at = COND #( WHEN ls_control_flag-created_at IS INITIAL
THEN ls_old-created_at )
created_by = COND #( WHEN ls_control_flag-created_by IS INITIAL
THEN ls_old-created_by )
last_changed_at = COND #( WHEN ls_control_flag-last_changed_at IS INITIAL
THEN lv_timestamp )
last_changed_by = COND #( WHEN ls_control_flag-last_changed_by IS INITIAL
THEN sy-uname )
) ).
ENDMETHOD.
METHOD read.
SELECT * FROM zsm_t_file_hand FOR ALL ENTRIES IN
WHERE document_id = -DocumentId
INTO TABLE (lt_result).
result = CORRESPONDING #( lt_result MAPPING TO ENTITY ).
ENDMETHOD.
METHOD delete.
DATA: lt_delete TYPE STANDARD TABLE OF zsm_t_file_hand.
lt_delete = CORRESPONDING #( keys MAPPING FROM ENTITY ).
gr_delete = VALUE #(
FOR ls_delete IN lt_delete
sign = ‘I’ option = ‘EQ’ ( low = ls_delete-document_id )
).
ENDMETHOD.
ENDCLASS. Step 7 : create the behavior definition for the Projection View.Step 8 : Create the Service definition for the consumption view.Step 9 : Create the Service Binding for Created Service definition and Choose the Binding type as OData V4 ,activate and publish the service.Preview the Application and click on create to upload the file.Click on upload icon near to the attachment field, select the file, file name will be auto filled and fill the Mime type manually. Read More Application Development Blog Posts articles
#SAP