[ABAP] Transportauftrag als ZIP-Datei speichern

SELECTION-SCREEN BEGIN OF LINE.
  SELECTION-SCREEN COMMENT (20) lbl1 FOR FIELD p_trkorr.
  PARAMETERS: p_trkorr LIKE e070-trkorr OBLIGATORY.
SELECTION-SCREEN END OF LINE.

INITIALIZATION.

  lbl1 = 'Transport-Auftrag:'.

START-OF-SELECTION.
  TRY.
      DATA: lv_req TYPE trwbo_request.

* (Nach-)Lesen von Einzelbestandteilen eines Auftrags
      CALL FUNCTION 'TR_READ_REQUEST'
        EXPORTING
          iv_read_e070     = abap_true
          iv_read_e07t     = abap_true
          iv_trkorr        = p_trkorr
        CHANGING
          cs_request       = lv_req
        EXCEPTIONS
          error_occured    = 1
          no_authorization = 2
          OTHERS           = 3.

      IF sy-subrc = 0.
*D Änderbar
*L Änderbar, geschützt
*O Freigabe gestartet
*R Freigegeben
*N Freigegeben (Importschutz für reparierte Objekte aktiv)
        IF lv_req-h-trstatus = 'R'.

          DATA: lv_trans_cofile_dir TYPE stpa-file.
          DATA: lv_trans_data_dir TYPE stpa-file.

* intern: Pfade der Transportverzeichnisse
          CALL FUNCTION 'TRINT_FI_GET_DIRECTORY_NAMES'
            EXPORTING
              iv_dir_type          = 'T'
            IMPORTING
              ev_data_dir          = lv_trans_data_dir
              ev_cofiles_dir       = lv_trans_cofile_dir
            EXCEPTIONS
              get_dir_trans_failed = 1
              build_path_failed    = 2
              OTHERS               = 3.

          IF sy-subrc = 0.
* Name
            DATA(lv_syst) = |{ p_trkorr(3) }|.
            DATA(lv_num) = |{ p_trkorr+4 }|.
            DATA(lv_name) = |{ lv_num }.{ lv_syst }|.

* Cofile lesen
            DATA: lv_xstr_cofile TYPE xstring.
            DATA(lv_cofile) = |{ lv_trans_cofile_dir }/K{ lv_name }|.

            OPEN DATASET lv_cofile FOR INPUT IN BINARY MODE.
            READ DATASET lv_cofile INTO lv_xstr_cofile.
            CLOSE DATASET lv_cofile.

* Data lesen
            DATA: lv_xstr_data TYPE xstring.
            DATA(lv_data) = |{ lv_trans_data_dir }/R{ lv_name }|.

            OPEN DATASET lv_data FOR INPUT IN BINARY MODE.
            READ DATASET lv_data INTO lv_xstr_data.
            CLOSE DATASET lv_data.

* Zip
            DATA(o_zip) = NEW cl_abap_zip( ).

            o_zip->add( name    = |K{ lv_name }|
                        content = lv_xstr_cofile ).

            o_zip->add( name    = |R{ lv_name }|
                        content = lv_xstr_data ).

            DATA(lv_xstr_zip) = o_zip->save( ).

* SOLIX
            DATA(it_raw_data) = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_xstr_zip ).

            DATA: lv_action TYPE i.
            DATA: lv_filename TYPE string.
            DATA: lv_fullpath TYPE string.
            DATA: lv_path TYPE string.

            DATA(lv_default) = |{ lv_req-h-as4text }_{ p_trkorr }|.

* alle Vorkommen, die nicht [a-zA-Z0-9_] entsprechen, durch '_' ersetzen
            REPLACE ALL OCCURRENCES OF REGEX '[^\w]+' IN lv_default WITH '_'.

* Save-Dialog
            cl_gui_frontend_services=>file_save_dialog( EXPORTING default_file_name = lv_default
                                                                  default_extension = 'zip'
                                                                  file_filter       = |{ cl_gui_frontend_services=>filetype_all }|
                                                        CHANGING  filename          = lv_filename
                                                                  path              = lv_path
                                                                  fullpath          = lv_fullpath
                                                                  user_action       = lv_action ).

            IF lv_action EQ cl_gui_frontend_services=>action_ok.

* Datei lokal speichern
              cl_gui_frontend_services=>gui_download( EXPORTING filename     = lv_fullpath
                                                                filetype     = 'BIN'
                                                                bin_filesize = xstrlen( lv_xstr_zip )
                                                      CHANGING  data_tab     = it_raw_data ).
            ENDIF.

          ELSE.
            WRITE: / |Systemverzeichnisse nicht gefunden.|.
          ENDIF.
        ELSE.
          WRITE: / |Auftrag { p_trkorr } nicht frei gegeben.|.
        ENDIF.

      ELSE.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO DATA(lv_msg).
        WRITE: / lv_msg.
      ENDIF.
    CATCH cx_root INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

[ABAP] Beliebige Dateien zu einer Zipdatei hinzufügen

TYPES: BEGIN OF bin_file,                          " Typ für Binärdatei mit Meta-Infos für das Zipfile
         name TYPE string,
         size TYPE i,
         data TYPE solix_tab,
       END OF bin_file.

DATA: lv_filename TYPE string.                     " Dateiname für FileOpen/FileSave
DATA: wa_file TYPE bin_file.                       " Binärdatei mit Meta-Infos für das Zipfile
DATA: it_binfiles TYPE STANDARD TABLE OF bin_file. " unkomprimierter Stream (Tabelle mit Dateien zum Zippen)
DATA: lv_path TYPE string.

START-OF-SELECTION.
* ZIP-Objekt erzeugen
  DATA(o_zip) = NEW cl_abap_zip( ).

  DATA: it_sel_filetab TYPE filetable.
  DATA: ret_code TYPE i.
  DATA: lv_action TYPE i.
* FileOpen-Dialog für Dateiauswahl anzeigen
* Mehrfachselektion möglich
  cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                window_title   = 'Dateien zum Komprimieren auswählen'
                                                multiselection = abap_true
                                              CHANGING
                                                file_table     = it_sel_filetab
                                                rc             = ret_code    " Anzahl ausgewählte Dateien, -1 bei Fehler
                                                user_action    = lv_action ).

  IF lv_action = cl_gui_frontend_services=>action_ok.

* Ausgewählte Dateien durchgehen
    LOOP AT it_sel_filetab INTO DATA(wa_sel_file).

      WRITE: / |Datei hinzugefügt: { wa_sel_file-filename }|.

* Dateien auf den Appl.-Server hochladen
      cl_gui_frontend_services=>gui_upload( EXPORTING
                                              filename   = |{ wa_sel_file-filename }|
                                              filetype   = 'BIN'
                                            IMPORTING
                                              filelength = wa_file-size
                                            CHANGING
                                              data_tab   = wa_file-data ).

* Pfad + Dateinamen aufsplitten
      CALL FUNCTION 'SO_SPLIT_FILE_AND_PATH'
        EXPORTING
          full_name     = wa_sel_file-filename
        IMPORTING
          file_path     = lv_path
          stripped_name = wa_file-name
        EXCEPTIONS
          x_error       = 1
          OTHERS        = 2.

* Datei zum Stream hinzufügen
      APPEND wa_file TO it_binfiles.

    ENDLOOP.

    ULINE.

    DATA: lv_xstring TYPE xstring.
* unkomprimierte Daten zum Zip-File hinzufügen
    LOOP AT it_binfiles INTO wa_file.

* jeden Datei-Stream binär zu xstring wandeln
      CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
        EXPORTING
          input_length = wa_file-size
        IMPORTING
          buffer       = lv_xstring
        TABLES
          binary_tab   = wa_file-data.

      o_zip->add( name    = wa_file-name
                  content = lv_xstring ).

    ENDLOOP.

* Daten komprimieren
    DATA(lv_zip) = o_zip->save( ).

    DATA: lv_zip_size TYPE i.
    DATA: it_zip_bin_data TYPE STANDARD TABLE OF raw255.

* xstring mit Zip-Daten zu binär rückwandeln
    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer        = lv_zip
      IMPORTING
        output_length = lv_zip_size
      TABLES
        binary_tab    = it_zip_bin_data.

    DATA: lv_dest_filepath TYPE string.

* SaveFile-Dialog aufrufen
    cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                  window_title         = 'Zipdatei speichern'
                                                  file_filter          = '(*.zip)|*.zip|'
                                                CHANGING
                                                  filename             = lv_filename
                                                  path                 = lv_path
                                                  fullpath             = lv_dest_filepath ).

* Zipdatei vom Appl-Server auf den lokalen Pfad speichern
    cl_gui_frontend_services=>gui_download( EXPORTING
                                              filename                = lv_dest_filepath
                                              filetype                = 'BIN'
                                              bin_filesize            = lv_zip_size
                                            CHANGING
                                              data_tab                = it_zip_bin_data ).

    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ELSE.
      WRITE: / |Zipdatei erfolgreich unter { lv_dest_filepath } gespeichert.|.
    ENDIF.
  ENDIF.