Send ZIP File Filled with PDF Files in OData, Media Handling in OData

Introduction

Recently I got a request for getting multiple PDFs from the service that was already in use, and I was already using ‘ GET_STREAM ‘ method to return a single PDF. Facing this request, the most quick and usable solution I thought was why not I am adding multiple PDFs into a single ZIP File, and then here we are.
I will be showing you  How to create a ZIP File filled with PDFs using OData.

Scenario

We will be using ‘ GET_STREAM ‘ method  of OData to get a single ZIP File, filled with PDFs that we will be creating from Adobeform.
Prerequisites:
1. Basic Knowledge about Adobeform2. Basic knowledge about OData3. Basic knowledge about SAP Gateway usage.Step-by-Step Procedure:
1. Creating the Odata Service and Redefining ‘ GET_STREAM ‘ Method.2. Creating a ZIP File  and filling it with PDFs.3. Registering the OData Service and testing it from SAP Gateway
STEP 1:
Firstly we need to create our ODATA Service. Go to SEGW and Create an OData project.
Create an ENTITY_TYPE responding your needs. Don’t forget to choose your entity as Media.

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Job, SAP ABAP Prep

Image 1 – Generating Service, Entity Types
Now generate Runtime Artifacts after that to Redefine the ‘ GET_STREAM ‘ method go to DPC_EXT section.

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Job, SAP ABAP Prep

Image 2 – Redefine GET_STREAM Method
STEP 2:
Now lets do what we know best, CODING. To get an easier to read code I prefer using Functions. These are ;
1. ‘ SO_PROFORMA_ZIP ‘ where I create  ZIP File and convert it to a xstring variable
2. ‘ SO_GET_PDF_VALUE ‘ where I get PDFs as xstring to add ZIP File
3. ‘ SO_PROFORMA_GET_DATA ‘  where I get my data to fill PDFs
In  ‘ SO_GET_PDF_VALUE ‘ Function, I am creating the PDFs and getting their xstring values.

FUNCTION so_get_pdf_value.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_VBELN) TYPE  VBELN
*"  EXPORTING
*"     VALUE(EV_VALUE) TYPE  FPCONTENT
*"----------------------------------------------------------------------

  DATA: ls_printout        TYPE so_proforma_st5,
        ls_fp_outputparams TYPE sfpoutputparams,
        lv_form_name       TYPE fpname,
        lv_fm_name         TYPE rs38l_fnam,
        ls_fp_docparams    TYPE sfpdocparams,
        ls_formoutput      TYPE fpformoutput,
        ls_result          TYPE sfpjoboutput.

  " Function where I Get Data to fill my PDF.
  CALL FUNCTION 'SO_PROFORMA_GET_DATA'
    EXPORTING
      iv_vbeln    = lv_vbeln
    IMPORTING
      es_printout = ls_printout.

  " Print data
  IF sy-cprog EQ 'RS_TESTFRAME_CALL'.
    sy-cprog = sy-repid.
  ENDIF.

* Do not forget to set your variables ! ! !
  ls_fp_outputparams-dest     = 'LP01'.
  ls_fp_outputparams-getpdf   = abap_true.
  ls_fp_outputparams-nodialog = abap_true.

  lv_form_name = 'SO_AF003'.

  CALL FUNCTION 'FP_JOB_OPEN'
    CHANGING
      ie_outputparams = ls_fp_outputparams
    EXCEPTIONS
      cancel          = 1
      usage_error     = 2
      system_error    = 3
      internal_error  = 4
      OTHERS          = 5.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  TRY.
      CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
        EXPORTING
          i_name     = lv_form_name
        IMPORTING
          e_funcname = lv_fm_name.
    CATCH cx_fp_api_repository.
    CATCH cx_fp_api_internal.
    CATCH cx_fp_api_usage.
  ENDTRY.

  ls_fp_docparams-langu = sy-langu.

  IF lv_fm_name IS NOT INITIAL.
    CALL FUNCTION lv_fm_name
      EXPORTING
        /1bcdwb/docparams  = ls_fp_docparams
        is_general         = ls_printout
      IMPORTING
        /1bcdwb/formoutput = ls_formoutput
      EXCEPTIONS
        usage_error        = 1
        system_error       = 2
        internal_error     = 3.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ELSE.
      ev_value = ls_formoutput-pdf. " PDF as xstring variable
    ENDIF.
  ENDIF.

  CALL FUNCTION 'FP_JOB_CLOSE'
    IMPORTING
      e_result       = ls_result
    EXCEPTIONS
      usage_error    = 1
      system_error   = 2
      internal_error = 3
      OTHERS         = 4.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

ENDFUNCTION.

In ‘ SO_PROFORMA_ZIP ‘ Function, I am creating the ZIP FILE filled with PDFs and converting it to xstring variable ( to be able to use it in get_stream method ),

FUNCTION so_proforma_zip.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_STRING) TYPE  STRING
*"  EXPORTING
*"     VALUE(EV_ZIPSTRING) TYPE  XSTRING
*"----------------------------------------------------------------------
  DATA: lo_zip         TYPE REF TO cl_abap_zip,
        lv_value       TYPE fpcontent,
        lv_filename    TYPE string,
        lt_vbeln       TYPE TABLE OF vbeln.

    SPLIT iv_string AT ',' INTO TABLE lt_vbeln.

    CREATE OBJECT lo_zip.

    LOOP AT lt_vbeln INTO DATA(lv_vbeln).

      CLEAR: lv_filename, lv_value.

      lv_filename = |{ lv_vbeln }.pdf|. " Name of the PDF File

      CALL FUNCTION 'SO_GET_PDF_VALUE' " Function where I get PDF as xstring value.
        EXPORTING
          iv_vbeln = lv_vbeln
        IMPORTING
          ev_value = lv_value.

      IF lv_value IS NOT INITIAL.
*Add PDF Files into ZIP File.
        lo_zip->add( EXPORTING name    = lv_filename
                               content = lv_value ).
      ENDIF.
    ENDLOOP.

    ev_zipxstring = lo_zip->save( ). " the final ZIP File.

  ENDIF.

ENDFUNCTION.

With this we are done with creating PDFs and adding them to ZIP FILE. Now what left is, consuming this ZIP FILE via ‘ GET_STREAM ‘ method of our OData service.
Define your variables as you need, and we are almost done. Do not forget to set mime_type variable as mime_type = ‘application/zip’ , If not you wont be getting any ZIP FILES. ( If you want to you can set several different mime_types like JPEG, PDF …. )

METHOD /iwbep/if_mgw_appl_srv_runtime~get_stream.

  CASE iv_entity_set_name.
    WHEN 'printSalesSet'.
*In our scenario we are using VBELN numbers seperated by ', ' in a string variable.
      DATA(lv_string) = VALUE #( it_key_tab[ 1 ]-value OPTIONAL ). " VBELN numbers seperated via ', '
      DATA(stream)   = VALUE ty_s_media_resource( mime_type = 'application/zip' ). " Media Source
      DATA(filename)   ='SalesOrders.zip'.

      CALL FUNCTION 'SO_PROFORMA_ZIP' "Function to get ZIP FILE content as a xstring value.
        EXPORTING
          iv_string     = lv_string
        IMPORTING
          ev_zipxstring = stream-value.

      set_header( VALUE #( name = 'Content-Disposition' value = |inline; filename="{ escape( val = filename format = cl_abap_format=>e_url ) }"| ) ).
      copy_data_to_ref( EXPORTING is_data = stream CHANGING cr_data = er_stream ).

  ENDCASE.

ENDMETHOD.
we are done with coding. now lets get our zip file.



STEP 3:
Go to t-code ‘ /N/IWFND/MAINT_SERVICE ‘ where we activate and maintain services. If you did not activate your service before, click to ‘ Add Service ‘ and activate your service. If you already did it, click ‘ FILTER ‘ and find your service

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Job, SAP ABAP Prep

Image 3 – Maintain Service
Double click your service and go to ‘ SAP Gateway Client ‘ where we will test our ODATA.

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Job, SAP ABAP Prep

Image 4 – SAP Gateway Client
Firstly select your EntitySet which we will be sending request. Fill your variables as responding to your needs and responding how did you set your entity key(s), in my case I will be using VBELN numbers separated by ‘, ‘.  Do not forget to add  ‘ /$value ‘  to end of your code. Without /$value addition our request wont be reaching ‘ GET_STREAM ‘ method of OData service. If you are done execute your code.

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Job, SAP ABAP Prep

Image 5 – Send a request to service
If you followed the blog well you will be seeing this screen with  ~status_code  = 200 and ~status_reason = OK. This means our service worked well and we did get our response, which is the ZIP File we created. You can also see your settings from here such as your mime_type which is content_type and your File Name which is  ~content_filename.

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Job, SAP ABAP Prep

Image 6 – Receive the response
Now Click ‘ Response in Browser ‘ and select ZIP file. Here it is your ZIP FILE filled with PDFs.

Regards!