cancel
Showing results for 
Search instead for 
Did you mean: 

Generate PDF file in backend, and "send" it to SAP Gateway

Former Member
0 Kudos

Hi

We want to generate PDF file in SAP backend, and when it is done, we want to send it via SAP Gateway.

A user will push a button, and it will create a report/pdf file with data from backend.

When the pdf file is done, we want to send it back to the user via SAP Gateway.

Anyone who can guide me?

Thanks

Lars

Accepted Solutions (1)

Accepted Solutions (1)

Former Member

Hi Lars,

In order to consume the PDF, you'll need to make a few GW definitions that are a little out of the ordinary.

Firstly, let's assume you can define the PDF as an entity. To do this you will need some kind of key scheme, e.g. if it were a PDF of an invoice, you can use the invoice ID as the PRF ID as well.

When you define the PDF entity, you need to mark it as 'media' - there is a column for this in the Entity Builder view. 

The entity only needs 2 properties - the key and a Mimetype descriptor (string).

You should redefine the MPC_EXT DEFINE method to read like this (note, the names 'PDF' and 'MimeType' depend on the model definition, this is what they are called in my model).

data:

   lo_entity   type ref to /iwbep/if_mgw_odata_entity_typ,

   lo_property type ref to /iwbep/if_mgw_odata_property.

   super->define( ).

   lo_entity = model->get_entity_type( iv_entity_name = 'PDF' ).

   if lo_entity is bound.

     lo_property = lo_entity->get_property( iv_property_name = 'MimeType' ).

     lo_property->set_as_content_type( ).

   endif.


You need to implement the logic for binary extraction in a redefined /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM method of the DPC.


Here you declare a local variable of type ty_s_media_resource. This has two fields in it, 'mime_type' and 'value'. Place 'application/pdf' in the mime_type and your binary PDF in 'value'. use copy_data_to_ref to copy the local variable to the er_stream output parameter.


Call the URI as normal but add the suffix /$value to access the stream (PDF).


Sorry for brevity but time is short and you can find some longer blogs on the subject of file upload/download which is essentially doing the same thing (When you view a PDF, it is downloading the PDF file to your browser).


Regards


Ron.


Former Member
0 Kudos

Hello Ron Sargeant,

I want to upload a file like PDF or DOC from ui5 to backend, using oData.

I created a gateway service.

I know that I must redefine create_stream method, but I don't know how to do that.

Do you have an example, how to write this method in abap?

Thank you,

Mari

Former Member
0 Kudos

Hi Ron

Can I do as Chandra is describing, or do I also need to do as you describe?

Lars

Former Member
0 Kudos

Hi Lars,

What Chandra is describing is nothing to do with Gateway

In order to expose a binary representation (such as a PDF or photo)  of a resource through OData you need to use the media streaming solution. The client can then use the appropriate handling for the Mime type.

The following code is the tail end of an example of a SAP Office document (which is a PDF) which has been read into table lt_hex - this is converted to binary which is placed in the stream. You need something similar to this in the GET_STREAM logic.

* not very useful code prior to this which fills lt_hex is omitted

data: ls_stream    TYPE         ty_s_media_resource.

   data: lv_solix type solix.

   data: lv_input type i.

   describe table lt_hex lines lv_input.

   read table lt_hex into lv_solix index lv_input.

   lv_input = ( ( lv_input - 1 ) * 255 ).

   lv_input = lv_input + xstrlen( lv_solix-line ).

   call function 'SCMS_BINARY_TO_XSTRING'

     exporting

       input_length = lv_input

*     FIRST_LINE   = 0

*     LAST_LINE    = 0

     importing

       buffer       = ls_stream-value

     tables

       binary_tab   = lt_hex

     exceptions

       failed       = 1

       others       = 2.

   if sy-subrc <> 0.

* Implement suitable error handling here

   endif.

   ls_stream-mime_type = 'application/pdf'.

   copy_data_to_ref( exporting is_data = ls_stream

                                    changing  cr_data = er_stream ).

ChandraMahajan
Active Contributor
0 Kudos

The process I shared was more suitable for my scenario and to display the pdf in front end UI5 application. yes I even can achieve same result using GET_STREAM logic.

and  GET_STREAM way is most accurate and recommended one as you need not to generate temporary url using cache logic etc.

And Thanks to for providing more information on it

Regards,

Chandra

Former Member
0 Kudos

Hello Ron,

I try to upload a file in backend from ui5.

In my gateway service, is necessary to redefine create_stream?

Do you have some example how to write in abap method create_stream?

Thank you,

Mari

Answers (1)

Answers (1)

ChandraMahajan
Active Contributor
0 Kudos

Hi Lars,

you can refer my blog

Regards,

Chandra

Former Member
0 Kudos

Really good blog Chandra.

In my case I am printing via tcode iw3d, and as I see it, is SAP Script.

The print is stored in the spoolfile, but how can I send that to the Gateway?

regards

Lars

ChandraMahajan
Active Contributor
0 Kudos

Hi,

you can generate xstring from spool. google it and you will get the logic. once you get the xstring, then as mentioned in my blog, do the coding and create OData service.

Regards,

Chandra

Former Member
0 Kudos

I think it is correct now, but how do I see the pdf document?

Please note, that the backend and Gateway is installed on different systems.

My result now is:

- <m:properties>

<d:url>/sap/public/005056BC3D0C1EE3B6B4492F419E3CAE.PDF</d:url>

<d:docnum>000040077740</d:docnum>

</m:properties>


Thanks,


Lars

ChandraMahajan
Active Contributor
0 Kudos

Hi,

you can open the PDF file by appending host and port name to your url.

http://<host_name>:<port>/sap/public/005056BC3D0C1EE3B6B4492F419E3CAE.PDF

just type this address in your chrome browser which will show you PDF output.

Regards,

Chandra

Former Member
0 Kudos

http://xxxx.xxx.xx:5xxxx/sap/public/005056BC3D0C1EE3B6B4492F419E3CAE.PDF


Should I choose something else, that I can find in AL11?

ChandraMahajan
Active Contributor
0 Kudos

you need to type the recent output url. and also note that the generated url output will be seen till 60 seconds as set up in FM logic sapui5-display_smartform_pdf/Z_TEST_PDF_DISPLAY at master · CmIm/sapui5-display_smartform_pdf · GitH...

****Set the Cache Timeout - 60 seconds - we only need this in the cache

****long enough to build the page

  lo_cached_response->server_cache_expire_rel( expires_rel = 60 ).

as per your requirement you can change this value.


Now once you execute the odata service, you will get unique url and then just append the host name and open it in the browser.


Regards,

Chandra

Former Member
0 Kudos

Hi Chandra

When I do it within 60 seconds, I still got an error message

404   Not Found

Any suggestions?

Can I see anywhere if I am doing something wrong? (When I am debugging, I don't get any errors).

Lars



Former Member
0 Kudos

My code looks like this:


DATA :

   lv_app_type TYPE string,
   lv_guid TYPE guid_32,
   lo_cached_response TYPE REF TO if_http_response.
data: bindata TYPE  XSTRING.
data: xstring type xstring.
data: size1 TYPE abap_msize.
data: string type string.

   CALL FUNCTION 'Z_PM_ORDER_PRINT_GET_PDF'
     EXPORTING
       i_aufnr                    = i_aufnr
    IMPORTING
      O_PDF                      = o_pdf
      O_RETURN                   = o_return
    EXCEPTIONS
      SOMETHING_WENT_WRONG       = 1
      OTHERS                     = 2
             .
   IF sy-subrc <> 0.
* Implement suitable error handling here
   ENDIF.

  string = o_pdf.

CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
   EXPORTING
     text           string
*   MIMETYPE       = ' '
*   ENCODING       =
  IMPORTING
    BUFFER         = xstring
  EXCEPTIONS
    FAILED         = 1
    OTHERS         = 2
           .
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.





   CREATE OBJECT lo_cached_response
     TYPE
     cl_http_response
     EXPORTING
       add_c_msg = 1.

*****set the data and the headers
   lo_cached_response->set_data( o_pdf )."lv_pdf_xstring ).
   lv_app_type = '.PDF'.

   lo_cached_response->set_header_field( name = if_http_header_fields=>content_type
                                      value = lv_app_type ).
*****Set the Response Status
   lo_cached_response->set_status( code = 200 reason = 'OK' ).

*****Set the Cache Timeout - 60 seconds - we only need this in the cache
*****long enough to build the page
   lo_cached_response->server_cache_expire_rel( expires_rel = 60 ).
*
****Create a unique URL for the object and export URL
   CALL FUNCTION 'GUID_CREATE'
     IMPORTING
       ev_guid_32 = lv_guid.
   CONCATENATE '/sap/public' '/' lv_guid '.' 'PDF' INTO e_url.
****Cache the URL
   cl_http_server=>server_cache_upload( url = e_url
                                        response = lo_cached_response ).



Former Member
0 Kudos

Hi Lars,

Replies have "crossed in post", but as you can see, in my latest response the code is very similar. All you need to do is copy my example and drop all the cached response stuff.

Regards

Ron.

Former Member
0 Kudos

Hi Ron
It is done now, but I still need something.

I guess it is in method: /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM

where I have following code:

DATA: ls_media TYPE ty_s_media_resource.

   ls_media-mime_type = 'application/pdf' .
   ls_media-value     = 'x'. "how to replace this with valid data?


   copy_data_to_ref(
     EXPORTING
        is_data = ls_media
     CHANGING
        cr_data = er_stream
        ).


When I call

/sap/opu/odata/sap/ZGW_VH_SHOW_PDF_SRV/pdfset(docnum='000040077740')

I got a response with data


When I call

/sap/opu/odata/sap/ZGW_VH_SHOW_PDF_SRV/pdfset(docnum='000040077740')/$value


i got the response 200 OK, and the only text <RESPONSE_BODY />


Can you give me more help?


Thanks


Lars


ChandraMahajan
Active Contributor
0 Kudos

Hi,

Please refer blog

Regards,

Chandra

Former Member
0 Kudos

You already converted the binary to the variable "xstring" - that's it!


ls_media-mime_type = 'application/pdf' .

   ls_media-value     = xstring.

Former Member
0 Kudos

Thanks, I think it is (nearly) working now.

I call first the URL:

/sap/xxx/xxxx/sap/ZGW_VH_SHOW_PDF_SRV/pdfset(docnum='000040077740')

and after that:

/sap/xxx/xxxx/sap/ZGW_VH_SHOW_PDF_SRV/pdfset(docnum='000040077740')/$value

The only problem now, is that I got the message, that the file is damaged and could not be repaired.

Maybe that is from backend?

Former Member
0 Kudos

I would expect the original PDF data to be binary, so I don't get why your function is exporting the PDF as a string. That is suspect, normally I'd be converting binary to xstring, not string to xstring.