Der SAP Document Management Service (DMS) ist ein BTP-Service zur zentralen Verwaltung von Dokumenten und Dateien. Er bietet eine REST-API für Upload, Download, Versionierung und Metadatenverwaltung – ideal für RAP-Anwendungen, die Dateianhänge verwalten müssen.
Architektur und Konzept
Der Document Management Service fungiert als zentrale Dokumentenablage in der SAP Business Technology Platform:
┌─────────────────────────────────────────────────────────────────────────────┐│ SAP Document Management Service ││ ││ ┌──────────────────────────────────────────────────────────────────────┐ ││ │ ABAP Cloud Anwendung │ ││ │ ┌─────────────────────┐ ┌─────────────────────┐ │ ││ │ │ RAP Business │ │ HTTP Client │ │ ││ │ │ Object │──│ (REST Calls) │ │ ││ │ └─────────────────────┘ └──────────┬──────────┘ │ ││ └───────────────────────────────────────┼──────────────────────────────┘ ││ │ ││ ┌───────────────────────────────────────┼──────────────────────────────┐ ││ │ Communication Arrangement │ ││ │ ┌─────────────────────┐ ┌──────────┴──────────┐ │ ││ │ │ Outbound Service │ │ OAuth2 Token │ │ ││ │ │ (Destination) │ │ Management │ │ ││ │ └─────────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │ ││ ┌───────────────────────────────────────┼──────────────────────────────┐ ││ │ SAP DMS (BTP Service) │ ││ │ ┌─────────────────────┐ ┌──────────┴──────────┐ │ ││ │ │ Repository API │ │ Object Store │ │ ││ │ │ (REST) │ │ (Speicher) │ │ ││ │ └─────────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────────────────────┘Vorteile des DMS
| Aspekt | Beschreibung |
|---|---|
| Zentrale Ablage | Alle Dokumente an einem Ort |
| Versionierung | Automatische Versionskontrolle |
| Metadaten | Strukturierte Dokumenteigenschaften |
| Suche | Volltextsuche in Dokumenten |
| Sicherheit | Zugriffssteuerung und Audit-Trail |
| Skalierbarkeit | Cloud-native Architektur |
Setup und Konfiguration
1. DMS Service in BTP aktivieren
Im BTP Cockpit muss der Document Management Service aktiviert und ein Repository erstellt werden:
BTP Cockpit → Subaccount → Service Marketplace→ Document Management Service → Create Instance
Instance Name: my-dms-instancePlan: standardRepository: my-repository2. Communication Arrangement erstellen
In ABAP Cloud wird die Verbindung über ein Communication Arrangement konfiguriert:
" Communication Scenario für DMS" Wird im ADT angelegt unter:" Source Library → Communication ScenariosCommunication Scenario Definition (sap_com_0502):
Scenario ID: Z_DMS_INTEGRATIONDescription: SAP Document Management Service IntegrationOutbound Services: - HTTP Service: SAP_COM_0502 (Document Management) - OAuth2 Authentication3. Destination im BTP Cockpit
┌──────────────────────────────────────────────────────────────────┐│ Destination Configuration │├──────────────────────────────────────────────────────────────────┤│ Name: DMS_API ││ Type: HTTP ││ URL: https://api-sdm-di.cfapps.eu10.hana.ondemand.com ││ Proxy Type: Internet ││ Authentication: OAuth2ClientCredentials ││ ││ ┌─ OAuth2 Settings ───────────────────────────────────────────┐ ││ │ Client ID: <dms-client-id> │ ││ │ Client Secret: ******** │ ││ │ Token URL: https://<subaccount>.authentication.eu10... │ ││ └──────────────────────────────────────────────────────────────┘ │└──────────────────────────────────────────────────────────────────┘4. Communication Arrangement in ABAP
" Maintain Communication Arrangement in ADT oder Fiori App" App: Maintain Communication Arrangements
Arrangement ID: Z_DMS_ARRANGEMENTScenario: Z_DMS_INTEGRATIONCommunication System: DMS_SYSTEMOutbound Service: - Service ID: SAP_COM_0502 - Destination: DMS_APIDMS Client Klasse
Eine zentrale Klasse kapselt die DMS-Kommunikation:
CLASS zcl_dms_client DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. TYPES: BEGIN OF ty_document, id TYPE string, name TYPE string, content_type TYPE string, size TYPE i, created_at TYPE timestamp, modified_at TYPE timestamp, version TYPE string, END OF ty_document, tt_documents TYPE STANDARD TABLE OF ty_document WITH EMPTY KEY.
TYPES: BEGIN OF ty_upload_result, success TYPE abap_bool, document_id TYPE string, message TYPE string, END OF ty_upload_result.
METHODS: constructor RAISING cx_http_dest_provider_error,
upload_document IMPORTING iv_filename TYPE string iv_content_type TYPE string iv_content TYPE xstring iv_folder_id TYPE string OPTIONAL RETURNING VALUE(rs_result) TYPE ty_upload_result RAISING cx_web_http_client_error,
download_document IMPORTING iv_document_id TYPE string RETURNING VALUE(rv_content) TYPE xstring RAISING cx_web_http_client_error,
list_documents IMPORTING iv_folder_id TYPE string OPTIONAL iv_search TYPE string OPTIONAL RETURNING VALUE(rt_documents) TYPE tt_documents RAISING cx_web_http_client_error,
delete_document IMPORTING iv_document_id TYPE string RETURNING VALUE(rv_success) TYPE abap_bool RAISING cx_web_http_client_error.
PRIVATE SECTION. DATA: mo_http_client TYPE REF TO if_web_http_client, mv_base_url TYPE string, mv_repository TYPE string.
METHODS: create_http_client RAISING cx_http_dest_provider_error,
parse_document_response IMPORTING iv_json TYPE string RETURNING VALUE(rs_document) TYPE ty_document,
parse_documents_response IMPORTING iv_json TYPE string RETURNING VALUE(rt_documents) TYPE tt_documents.ENDCLASS.
CLASS zcl_dms_client IMPLEMENTATION. METHOD constructor. mv_repository = 'my-repository'. create_http_client( ). ENDMETHOD.
METHOD create_http_client. " HTTP Destination aus Communication Arrangement abrufen DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_DMS_INTEGRATION' service_id = 'SAP_COM_0502' ).
mo_http_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
" Base URL für DMS API mv_base_url = '/browser/' && mv_repository && '/root'. ENDMETHOD.
METHOD upload_document. DATA: lv_url TYPE string.
" URL für Upload erstellen IF iv_folder_id IS NOT INITIAL. lv_url = mv_base_url && '/' && iv_folder_id. ELSE. lv_url = mv_base_url. ENDIF.
" Request vorbereiten DATA(lo_request) = mo_http_client->get_http_request( ). lo_request->set_uri_path( lv_url ). lo_request->set_header_field( i_name = 'Content-Type' i_value = 'multipart/form-data' ).
" Multipart Body erstellen DATA: lv_boundary TYPE string VALUE '----WebKitFormBoundary7MA4YWxkTrZu0gW'.
DATA(lv_body) = |--{ lv_boundary }{ cl_abap_char_utilities=>cr_lf }| && |Content-Disposition: form-data; name="file"; filename="{ iv_filename }"{ cl_abap_char_utilities=>cr_lf }| && |Content-Type: { iv_content_type }{ cl_abap_char_utilities=>cr_lf }| && |{ cl_abap_char_utilities=>cr_lf }|.
" Content als Binary anhängen DATA(lv_body_xstring) = cl_abap_conv_codepage=>create_out( )->convert( lv_body ). lv_body_xstring = lv_body_xstring && iv_content.
DATA(lv_end) = |{ cl_abap_char_utilities=>cr_lf }--{ lv_boundary }--|. lv_body_xstring = lv_body_xstring && cl_abap_conv_codepage=>create_out( )->convert( lv_end ).
lo_request->set_binary_body( lv_body_xstring ). lo_request->set_header_field( i_name = 'Content-Type' i_value = |multipart/form-data; boundary={ lv_boundary }| ).
" Request senden DATA(lo_response) = mo_http_client->execute( if_web_http_client=>post ). DATA(lv_status) = lo_response->get_status( )-code.
IF lv_status = 201. rs_result-success = abap_true.
" Document ID aus Response extrahieren DATA(lv_json) = lo_response->get_text( ). DATA(ls_doc) = parse_document_response( lv_json ). rs_result-document_id = ls_doc-id. rs_result-message = 'Upload erfolgreich'. ELSE. rs_result-success = abap_false. rs_result-message = |Upload fehlgeschlagen: HTTP { lv_status }|. ENDIF. ENDMETHOD.
METHOD download_document. DATA(lv_url) = mv_base_url && '/' && iv_document_id && '?cmisselector=content'.
DATA(lo_request) = mo_http_client->get_http_request( ). lo_request->set_uri_path( lv_url ).
DATA(lo_response) = mo_http_client->execute( if_web_http_client=>get ). DATA(lv_status) = lo_response->get_status( )-code.
IF lv_status = 200. rv_content = lo_response->get_binary_body( ). ELSE. RAISE EXCEPTION TYPE cx_web_http_client_error. ENDIF. ENDMETHOD.
METHOD list_documents. DATA(lv_url) = mv_base_url && '?cmisselector=children'.
IF iv_folder_id IS NOT INITIAL. lv_url = mv_base_url && '/' && iv_folder_id && '?cmisselector=children'. ENDIF.
IF iv_search IS NOT INITIAL. lv_url = lv_url && '&filter=' && cl_web_http_utility=>escape_url( iv_search ). ENDIF.
DATA(lo_request) = mo_http_client->get_http_request( ). lo_request->set_uri_path( lv_url ).
DATA(lo_response) = mo_http_client->execute( if_web_http_client=>get ). DATA(lv_status) = lo_response->get_status( )-code.
IF lv_status = 200. DATA(lv_json) = lo_response->get_text( ). rt_documents = parse_documents_response( lv_json ). ENDIF. ENDMETHOD.
METHOD delete_document. DATA(lv_url) = mv_base_url && '/' && iv_document_id.
DATA(lo_request) = mo_http_client->get_http_request( ). lo_request->set_uri_path( lv_url ).
DATA(lo_response) = mo_http_client->execute( if_web_http_client=>delete ). DATA(lv_status) = lo_response->get_status( )-code.
rv_success = xsdbool( lv_status = 204 OR lv_status = 200 ). ENDMETHOD.
METHOD parse_document_response. " JSON Response parsen " Beispiel: {"objectId":"doc123","name":"test.pdf","size":12345} DATA: lr_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = iv_json CHANGING data = lr_data ).
" Feldzuordnung FIELD-SYMBOLS: <ls_data> TYPE any. ASSIGN lr_data->* TO <ls_data>. IF sy-subrc = 0. ASSIGN COMPONENT 'objectId' OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<lv_id>). IF sy-subrc = 0. rs_document-id = <lv_id>. ENDIF.
ASSIGN COMPONENT 'name' OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<lv_name>). IF sy-subrc = 0. rs_document-name = <lv_name>. ENDIF. ENDIF. ENDMETHOD.
METHOD parse_documents_response. " JSON Array parsen DATA: lr_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = iv_json CHANGING data = lr_data ).
" Array durchlaufen und Dokumente extrahieren FIELD-SYMBOLS: <lt_objects> TYPE ANY TABLE. ASSIGN lr_data->* TO <lt_objects>. IF sy-subrc = 0. LOOP AT <lt_objects> ASSIGNING FIELD-SYMBOL(<ls_object>). DATA(ls_doc) = VALUE ty_document( ).
ASSIGN COMPONENT 'objectId' OF STRUCTURE <ls_object> TO FIELD-SYMBOL(<lv_id>). IF sy-subrc = 0. ls_doc-id = <lv_id>. ENDIF.
ASSIGN COMPONENT 'name' OF STRUCTURE <ls_object> TO FIELD-SYMBOL(<lv_name>). IF sy-subrc = 0. ls_doc-name = <lv_name>. ENDIF.
APPEND ls_doc TO rt_documents. ENDLOOP. ENDIF. ENDMETHOD.ENDCLASS.Datei hochladen (Upload)
Der Upload erfolgt als Multipart-Request mit dem Dateiinhalt:
CLASS zcl_document_handler DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. METHODS upload_file IMPORTING iv_filename TYPE string iv_content TYPE xstring iv_content_type TYPE string RETURNING VALUE(rv_document_id) TYPE string RAISING cx_web_http_client_error cx_http_dest_provider_error.ENDCLASS.
CLASS zcl_document_handler IMPLEMENTATION. METHOD upload_file. DATA(lo_dms) = NEW zcl_dms_client( ).
DATA(ls_result) = lo_dms->upload_document( iv_filename = iv_filename iv_content_type = iv_content_type iv_content = iv_content ).
IF ls_result-success = abap_true. rv_document_id = ls_result-document_id. ELSE. " Fehlerbehandlung RAISE EXCEPTION TYPE cx_web_http_client_error. ENDIF. ENDMETHOD.ENDCLASS.Upload aus RAP Action
" In der Behavior ImplementationMETHOD upload_attachment. DATA(lo_handler) = NEW zcl_document_handler( ).
TRY. DATA(lv_doc_id) = lo_handler->upload_file( iv_filename = keys[ 1 ]-%param-filename iv_content = keys[ 1 ]-%param-content iv_content_type = keys[ 1 ]-%param-content_type ).
" Document ID speichern MODIFY ENTITIES OF zi_document IN LOCAL MODE ENTITY Document UPDATE FIELDS ( DmsDocumentId ) WITH VALUE #( ( %tky = keys[ 1 ]-%tky DmsDocumentId = lv_doc_id ) ).
CATCH cx_web_http_client_error cx_http_dest_provider_error INTO DATA(lx_error). APPEND VALUE #( %tky = keys[ 1 ]-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = lx_error->get_text( ) ) ) TO reported-document. ENDTRY.ENDMETHOD.Datei herunterladen (Download)
Der Download gibt den Dateiinhalt als Binary-Stream zurück:
METHOD download_attachment. DATA(lo_dms) = NEW zcl_dms_client( ).
" Document ID aus Entity lesen READ ENTITIES OF zi_document IN LOCAL MODE ENTITY Document FIELDS ( DmsDocumentId FileName ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_documents).
IF lt_documents IS INITIAL. RETURN. ENDIF.
DATA(ls_doc) = lt_documents[ 1 ].
TRY. DATA(lv_content) = lo_dms->download_document( iv_document_id = ls_doc-DmsDocumentId ).
" Content an Result übergeben result = VALUE #( ( %tky = keys[ 1 ]-%tky %param = VALUE #( content = lv_content filename = ls_doc-FileName content_type = 'application/octet-stream' ) ) ).
CATCH cx_web_http_client_error INTO DATA(lx_error). APPEND VALUE #( %tky = keys[ 1 ]-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = |Download fehlgeschlagen: { lx_error->get_text( ) }| ) ) TO reported-document. ENDTRY.ENDMETHOD.Dateien auflisten und suchen
Das Auflisten und Suchen von Dokumenten erfolgt über die List-API:
METHOD list_documents. DATA(lo_dms) = NEW zcl_dms_client( ).
TRY. " Alle Dokumente im Root-Ordner DATA(lt_all_docs) = lo_dms->list_documents( ).
" Mit Suchfilter DATA(lt_filtered_docs) = lo_dms->list_documents( iv_search = 'invoice' ).
" In einem bestimmten Ordner DATA(lt_folder_docs) = lo_dms->list_documents( iv_folder_id = 'folder-123' ).
" Ergebnis verarbeiten LOOP AT lt_all_docs INTO DATA(ls_doc). " Dokument-Metadaten verwenden DATA(lv_id) = ls_doc-id. DATA(lv_name) = ls_doc-name. DATA(lv_size) = ls_doc-size. ENDLOOP.
CATCH cx_web_http_client_error INTO DATA(lx_error). " Fehlerbehandlung ENDTRY.ENDMETHOD.Suchfunktion mit Volltextsuche
METHOD search_documents. DATA(lo_dms) = NEW zcl_dms_client( ).
" CMIS Query für erweiterte Suche DATA(lv_url) = '/browser/my-repository/root?cmisselector=query&q=' && cl_web_http_utility=>escape_url( |SELECT * FROM cmis:document WHERE CONTAINS('{ iv_search_term }')| ).
TRY. DATA(lo_request) = mo_http_client->get_http_request( ). lo_request->set_uri_path( lv_url ).
DATA(lo_response) = mo_http_client->execute( if_web_http_client=>get ).
IF lo_response->get_status( )-code = 200. " Suchergebnisse parsen DATA(lv_json) = lo_response->get_text( ). rt_results = parse_search_results( lv_json ). ENDIF.
CATCH cx_web_http_client_error INTO DATA(lx_error). " Fehlerbehandlung ENDTRY.ENDMETHOD.Datei loeschen
Das Loeschen erfolgt ueber die DELETE-Methode:
METHOD delete_attachment. DATA(lo_dms) = NEW zcl_dms_client( ).
" Document ID aus Entity lesen READ ENTITIES OF zi_document IN LOCAL MODE ENTITY Document FIELDS ( DmsDocumentId ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_documents).
IF lt_documents IS INITIAL. RETURN. ENDIF.
TRY. DATA(lv_success) = lo_dms->delete_document( iv_document_id = lt_documents[ 1 ]-DmsDocumentId ).
IF lv_success = abap_true. " DMS ID aus Entity entfernen MODIFY ENTITIES OF zi_document IN LOCAL MODE ENTITY Document UPDATE FIELDS ( DmsDocumentId ) WITH VALUE #( ( %tky = keys[ 1 ]-%tky DmsDocumentId = '' ) ). ELSE. APPEND VALUE #( %tky = keys[ 1 ]-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Loeschen fehlgeschlagen' ) ) TO reported-document. ENDIF.
CATCH cx_web_http_client_error INTO DATA(lx_error). APPEND VALUE #( %tky = keys[ 1 ]-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = lx_error->get_text( ) ) ) TO reported-document. ENDTRY.ENDMETHOD.Fehlerbehandlung und Retry-Logik
Bei der Kommunikation mit externen Services ist robuste Fehlerbehandlung wichtig:
CLASS zcl_dms_client_robust DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. CONSTANTS: c_max_retries TYPE i VALUE 3, c_retry_delay TYPE i VALUE 1000. " Millisekunden
METHODS: upload_with_retry IMPORTING iv_filename TYPE string iv_content_type TYPE string iv_content TYPE xstring RETURNING VALUE(rs_result) TYPE zcl_dms_client=>ty_upload_result.
PRIVATE SECTION. DATA: mo_dms_client TYPE REF TO zcl_dms_client.
METHODS: is_retryable_error IMPORTING ix_error TYPE REF TO cx_root RETURNING VALUE(rv_retryable) TYPE abap_bool,
wait_before_retry IMPORTING iv_attempt TYPE i.ENDCLASS.
CLASS zcl_dms_client_robust IMPLEMENTATION. METHOD upload_with_retry. DATA: lv_attempt TYPE i VALUE 0, lx_last_error TYPE REF TO cx_root.
" Client erstellen falls noch nicht vorhanden IF mo_dms_client IS NOT BOUND. TRY. mo_dms_client = NEW zcl_dms_client( ). CATCH cx_http_dest_provider_error INTO DATA(lx_dest_error). rs_result-success = abap_false. rs_result-message = lx_dest_error->get_text( ). RETURN. ENDTRY. ENDIF.
" Retry-Loop WHILE lv_attempt < c_max_retries. lv_attempt = lv_attempt + 1.
TRY. rs_result = mo_dms_client->upload_document( iv_filename = iv_filename iv_content_type = iv_content_type iv_content = iv_content ).
IF rs_result-success = abap_true. RETURN. " Erfolg ENDIF.
CATCH cx_web_http_client_error INTO DATA(lx_http_error). lx_last_error = lx_http_error.
IF is_retryable_error( lx_http_error ) AND lv_attempt < c_max_retries. wait_before_retry( lv_attempt ). CONTINUE. " Retry ENDIF. ENDTRY. ENDWHILE.
" Alle Versuche fehlgeschlagen rs_result-success = abap_false. IF lx_last_error IS BOUND. rs_result-message = |Upload nach { c_max_retries } Versuchen fehlgeschlagen: { lx_last_error->get_text( ) }|. ENDIF. ENDMETHOD.
METHOD is_retryable_error. " HTTP 5xx Fehler und Timeout sind retryable rv_retryable = abap_true.
" Spezifische Fehlertypen prüfen DATA(lx_http_error) = CAST cx_web_http_client_error( ix_error OPTIONAL ). IF lx_http_error IS BOUND. " Nur bei temporären Fehlern retry " 4xx Fehler (Client-Fehler) sind nicht retryable rv_retryable = abap_true. ENDIF. ENDMETHOD.
METHOD wait_before_retry. " Exponential Backoff: 1s, 2s, 4s DATA(lv_delay) = c_retry_delay * ( 2 ** ( iv_attempt - 1 ) ).
" In ABAP Cloud: WAIT für kurze Pausen DATA(lv_end_time) = utclong_current( ) + CONV utclong( lv_delay / 1000 ). WHILE utclong_current( ) < lv_end_time. " Warten ENDWHILE. ENDMETHOD.ENDCLASS.Fehlertypen und Behandlung
| HTTP Status | Fehlertyp | Aktion |
|---|---|---|
| 400 | Bad Request | Eingabe prüfen, nicht retry |
| 401 | Unauthorized | Token refresh, dann retry |
| 403 | Forbidden | Berechtigungen prüfen |
| 404 | Not Found | Dokument existiert nicht |
| 409 | Conflict | Versionskonflikt, neu laden |
| 429 | Too Many Requests | Backoff und retry |
| 500 | Server Error | Retry mit Backoff |
| 503 | Service Unavailable | Retry mit Backoff |
Logging und Monitoring
METHOD log_dms_operation. " Application Log für DMS-Operationen DATA(lo_log) = cl_bali_log=>create_with_header( header = cl_bali_header_setter=>create( object = 'Z_DMS' subobject = 'OPERATIONS' external_id = iv_document_id ) ).
CASE iv_operation. WHEN 'UPLOAD'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_free_text text = |Dokument hochgeladen: { iv_filename }| ) ).
WHEN 'DOWNLOAD'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_free_text text = |Dokument heruntergeladen: { iv_document_id }| ) ).
WHEN 'DELETE'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_free_text text = |Dokument geloescht: { iv_document_id }| ) ).
WHEN 'ERROR'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_error text = |Fehler: { iv_error_message }| ) ). ENDCASE.
cl_bali_log_db=>get_instance( )->save_log( log = lo_log ).ENDMETHOD.Best Practices
1. Content-Type korrekt setzen
" Content-Type aus Dateiendung ermittelnMETHOD get_content_type. CASE to_lower( iv_extension ). WHEN 'pdf'. rv_content_type = 'application/pdf'. WHEN 'docx'. rv_content_type = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'. WHEN 'xlsx'. rv_content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'. WHEN 'png'. rv_content_type = 'image/png'. WHEN 'jpg' OR 'jpeg'. rv_content_type = 'image/jpeg'. WHEN OTHERS. rv_content_type = 'application/octet-stream'. ENDCASE.ENDMETHOD.2. Grosse Dateien chunked uebertragen
" Fuer grosse Dateien: Chunked UploadCONSTANTS: c_chunk_size TYPE i VALUE 5242880. " 5 MB
METHOD upload_large_file. DATA: lv_offset TYPE i VALUE 0, lv_chunk TYPE xstring.
WHILE lv_offset < xstrlen( iv_content ). lv_chunk = iv_content+lv_offset(c_chunk_size).
" Chunk hochladen upload_chunk( iv_session_id = iv_session_id iv_offset = lv_offset iv_chunk = lv_chunk ).
lv_offset = lv_offset + c_chunk_size. ENDWHILE.ENDMETHOD.3. Metadaten strukturiert speichern
" Metadaten als JSON im DMS speichernDATA(ls_metadata) = VALUE ty_document_metadata( created_by = sy-uname created_at = utclong_current( ) business_object = 'SALESORDER' business_key = '0000001234' document_type = 'INVOICE').
DATA(lv_metadata_json) = /ui2/cl_json=>serialize( data = ls_metadata ).Verwandte Themen
- HTTP Client in ABAP Cloud – REST-APIs aufrufen
- Attachment Handling in RAP – Dateianhänge in RAP-Anwendungen
- SAP Destination Service – Externe Systeme sicher anbinden
Fazit
Der SAP Document Management Service bietet eine robuste, cloud-native Lösung für Dokumentenverwaltung in ABAP Cloud. Mit der richtigen Architektur – Communication Arrangements, HTTP-Client und strukturierter Fehlerbehandlung – lässt sich DMS nahtlos in RAP-Anwendungen integrieren.