Le SAP Document Management Service (DMS) est un service BTP pour la gestion centralisée de documents et de fichiers. Il offre une API REST pour le téléversement, le téléchargement, la gestion des versions et des métadonnées – idéal pour les applications RAP qui doivent gérer des pièces jointes.
Architecture et concept
Le Document Management Service fonctionne comme un référentiel central de documents dans la SAP Business Technology Platform :
┌─────────────────────────────────────────────────────────────────────────────┐│ SAP Document Management Service ││ ││ ┌──────────────────────────────────────────────────────────────────────┐ ││ │ Application ABAP Cloud │ ││ │ ┌─────────────────────┐ ┌─────────────────────┐ │ ││ │ │ RAP Business │ │ HTTP Client │ │ ││ │ │ Object │──│ (Appels REST) │ │ ││ │ └─────────────────────┘ └──────────┬──────────┘ │ ││ └───────────────────────────────────────┼──────────────────────────────┘ ││ │ ││ ┌───────────────────────────────────────┼──────────────────────────────┐ ││ │ Communication Arrangement │ ││ │ ┌─────────────────────┐ ┌──────────┴──────────┐ │ ││ │ │ Outbound Service │ │ Gestion Token │ │ ││ │ │ (Destination) │ │ OAuth2 │ │ ││ │ └─────────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │ ││ ┌───────────────────────────────────────┼──────────────────────────────┐ ││ │ SAP DMS (Service BTP) │ ││ │ ┌─────────────────────┐ ┌──────────┴──────────┐ │ ││ │ │ Repository API │ │ Object Store │ │ ││ │ │ (REST) │ │ (Stockage) │ │ ││ │ └─────────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────────────────────┘Avantages du DMS
| Aspect | Description |
|---|---|
| Stockage central | Tous les documents au même endroit |
| Versionnement | Contrôle automatique des versions |
| Métadonnées | Propriétés de documents structurées |
| Recherche | Recherche plein texte dans les documents |
| Sécurité | Contrôle d’accès et piste d’audit |
| Évolutivité | Architecture cloud-native |
Configuration et paramétrage
1. Activer le service DMS dans BTP
Dans le cockpit BTP, le Document Management Service doit être activé et un référentiel créé :
BTP Cockpit → Subaccount → Service Marketplace→ Document Management Service → Create Instance
Instance Name: my-dms-instancePlan: standardRepository: my-repository2. Créer un Communication Arrangement
Dans ABAP Cloud, la connexion est configurée via un Communication Arrangement :
" Communication Scenario pour DMS" Créé dans ADT sous :" Source Library → Communication ScenariosDéfinition du Communication Scenario (sap_com_0502) :
Scenario ID: Z_DMS_INTEGRATIONDescription: SAP Document Management Service IntegrationOutbound Services: - HTTP Service: SAP_COM_0502 (Document Management) - OAuth2 Authentication3. Destination dans le cockpit BTP
┌──────────────────────────────────────────────────────────────────┐│ Configuration Destination │├──────────────────────────────────────────────────────────────────┤│ Name: DMS_API ││ Type: HTTP ││ URL: https://api-sdm-di.cfapps.eu10.hana.ondemand.com ││ Proxy Type: Internet ││ Authentication: OAuth2ClientCredentials ││ ││ ┌─ Paramètres OAuth2 ───────────────────────────────────────────┐ ││ │ Client ID: <dms-client-id> │ ││ │ Client Secret: ******** │ ││ │ Token URL: https://<subaccount>.authentication.eu10... │ ││ └──────────────────────────────────────────────────────────────┘ │└──────────────────────────────────────────────────────────────────┘4. Communication Arrangement dans ABAP
" Gérer le Communication Arrangement dans ADT ou 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_APIClasse client DMS
Une classe centrale encapsule la communication avec le DMS :
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. " Récupérer la destination HTTP depuis le Communication Arrangement 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 ).
" URL de base pour l'API DMS mv_base_url = '/browser/' && mv_repository && '/root'. ENDMETHOD.
METHOD upload_document. DATA: lv_url TYPE string.
" Créer l'URL pour le téléversement IF iv_folder_id IS NOT INITIAL. lv_url = mv_base_url && '/' && iv_folder_id. ELSE. lv_url = mv_base_url. ENDIF.
" Préparer la requête 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" ).
" Créer le corps multipart 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 }|.
" Ajouter le contenu en binaire 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 }| ).
" Envoyer la requête 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.
" Extraire l'ID du document de la réponse 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 = 'Téléversement réussi'. ELSE. rs_result-success = abap_false. rs_result-message = |Échec du téléversement : 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. " Analyser la réponse JSON " Exemple : {"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 ).
" Assignation des champs 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. " Analyser le tableau JSON DATA: lr_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = iv_json CHANGING data = lr_data ).
" Parcourir le tableau et extraire les documents 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.Téléverser un fichier (Upload)
Le téléversement s’effectue en tant que requête multipart avec le contenu du fichier :
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. " Gestion des erreurs RAISE EXCEPTION TYPE cx_web_http_client_error. ENDIF. ENDMETHOD.ENDCLASS.Téléversement depuis une action RAP
" Dans l'implémentation du BehaviorMETHOD 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 ).
" Sauvegarder l'ID du document 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.Télécharger un fichier (Download)
Le téléchargement retourne le contenu du fichier sous forme de flux binaire :
METHOD download_attachment. DATA(lo_dms) = NEW zcl_dms_client( ).
" Lire l'ID du document depuis l'entité 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 ).
" Passer le contenu au résultat 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 = |Échec du téléchargement : { lx_error->get_text( ) }| ) ) TO reported-document. ENDTRY.ENDMETHOD.Lister et rechercher des fichiers
Le listage et la recherche de documents s’effectuent via l’API de liste :
METHOD list_documents. DATA(lo_dms) = NEW zcl_dms_client( ).
TRY. " Tous les documents dans le dossier racine DATA(lt_all_docs) = lo_dms->list_documents( ).
" Avec filtre de recherche DATA(lt_filtered_docs) = lo_dms->list_documents( iv_search = 'invoice" ).
" Dans un dossier spécifique DATA(lt_folder_docs) = lo_dms->list_documents( iv_folder_id = 'folder-123" ).
" Traiter les résultats LOOP AT lt_all_docs INTO DATA(ls_doc). " Utiliser les métadonnées du document 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). " Gestion des erreurs ENDTRY.ENDMETHOD.Fonction de recherche avec recherche plein texte
METHOD search_documents. DATA(lo_dms) = NEW zcl_dms_client( ).
" Requête CMIS pour recherche avancée 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. " Analyser les résultats de recherche 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). " Gestion des erreurs ENDTRY.ENDMETHOD.Supprimer un fichier
La suppression s’effectue via la méthode DELETE :
METHOD delete_attachment. DATA(lo_dms) = NEW zcl_dms_client( ).
" Lire l'ID du document depuis l'entité 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. " Supprimer l'ID DMS de l'entité 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 = 'Échec de la suppression' ) ) 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.Gestion des erreurs et logique de réessai
Lors de la communication avec des services externes, une gestion robuste des erreurs est importante :
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. " Millisecondes
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.
" Créer le client si pas encore instancié 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.
" Boucle de réessai 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. " Succès 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. " Réessayer ENDIF. ENDTRY. ENDWHILE.
" Toutes les tentatives ont échoué rs_result-success = abap_false. IF lx_last_error IS BOUND. rs_result-message = |Téléversement échoué après { c_max_retries } tentatives : { lx_last_error->get_text( ) }|. ENDIF. ENDMETHOD.
METHOD is_retryable_error. " Les erreurs HTTP 5xx et timeout sont réessayables rv_retryable = abap_true.
" Vérifier les types d'erreurs spécifiques DATA(lx_http_error) = CAST cx_web_http_client_error( ix_error OPTIONAL ). IF lx_http_error IS BOUND. " Réessayer uniquement pour les erreurs temporaires " Les erreurs 4xx (erreurs client) ne sont pas réessayables rv_retryable = abap_true. ENDIF. ENDMETHOD.
METHOD wait_before_retry. " Backoff exponentiel : 1s, 2s, 4s DATA(lv_delay) = c_retry_delay * ( 2 ** ( iv_attempt - 1 ) ).
" Dans ABAP Cloud : WAIT pour des pauses courtes DATA(lv_end_time) = utclong_current( ) + CONV utclong( lv_delay / 1000 ). WHILE utclong_current( ) < lv_end_time. " Attendre ENDWHILE. ENDMETHOD.ENDCLASS.Types d’erreurs et gestion
| Statut HTTP | Type d’erreur | Action |
|---|---|---|
| 400 | Bad Request | Vérifier l’entrée, pas de réessai |
| 401 | Unauthorized | Rafraîchir le token, puis réessayer |
| 403 | Forbidden | Vérifier les autorisations |
| 404 | Not Found | Le document n’existe pas |
| 409 | Conflict | Conflit de version, recharger |
| 429 | Too Many Requests | Backoff et réessai |
| 500 | Server Error | Réessai avec backoff |
| 503 | Service Unavailable | Réessai avec backoff |
Journalisation et monitoring
METHOD log_dms_operation. " Log d'application pour les opérations DMS 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 = |Document téléversé : { iv_filename }| ) ).
WHEN 'DOWNLOAD'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_free_text text = |Document téléchargé : { iv_document_id }| ) ).
WHEN 'DELETE'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_free_text text = |Document supprimé : { iv_document_id }| ) ).
WHEN 'ERROR'. lo_log->add_item( cl_bali_message_setter=>create( severity = if_bali_constants=>c_category_error text = |Erreur : { iv_error_message }| ) ). ENDCASE.
cl_bali_log_db=>get_instance( )->save_log( log = lo_log ).ENDMETHOD.Bonnes pratiques
1. Définir correctement le Content-Type
" Déterminer le Content-Type à partir de l'extension de fichierMETHOD 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. Transférer les gros fichiers par morceaux
" Pour les gros fichiers : téléversement par morceauxCONSTANTS: c_chunk_size TYPE i VALUE 5242880. " 5 Mo
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).
" Téléverser le morceau 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. Stocker les métadonnées de manière structurée
" Stocker les métadonnées en JSON dans le DMSDATA(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 ).Sujets connexes
- Client HTTP dans ABAP Cloud – Appeler des API REST
- Gestion des pièces jointes dans RAP – Pièces jointes dans les applications RAP
- SAP Destination Service – Connecter de manière sécurisée des systèmes externes
Conclusion
Le SAP Document Management Service offre une solution robuste et cloud-native pour la gestion de documents dans ABAP Cloud. Avec la bonne architecture – Communication Arrangements, client HTTP et gestion structurée des erreurs – le DMS peut être intégré de manière transparente dans les applications RAP.