UPDATE JUNE 2014: Please note that in the blog below I create custom RFCs for this purpose which I would no longer recommend. As discussed in the comments made by Ron Sargeant to this blog and also in his own blog Improved Inside-Out Modelling where also Krishna Kishor Kammaje joins in the discussion a code based approach would have been a far more elegant solution than creating custom RFCs. I hope to update this blog with a code based implementation of the same sometime in the future.
The aim of this blog is to provide a step by step approach enabling anyone that needs a gateway service to upload/download files to SAP backend to develop it in no time.
In this blog I have listed some existing blogs and SCN posts regarding this topic. These have helped me manage to develop my upload/download service but none of them give a full step by step approach of how to do this and they refer to different versions of Gateway.
Note that in my examples the values contained in <> needs to be substituted with your own values 😉
1. Create Table
First I created a table to contain the uploaded files with the following properties:
You can of course adjust these properties to your need but the mimetype and value (stored as rawstring) will always be needed.
2. Develop Function Modules
Two Remote Function Modules was then developed. One that can upload a file to the table above and one that downloads from it.
The upload RFC has these import parameters and simply dumps the input into the table:
The download RFC takes the key values PERNR and FILENAME as input and exports:
It simply executes a read on the table using the key values and sets the export parameters.
Remember to mark the function modules as remote enabled 🙂
3. Create Project in SEGW and Entity Types
A project was created in SEGW and an entity type based on the download function module (right click Data Model->Import->RFC/BOR interface) created giving the properties as shown below:
On the actual entity, that I have called “File”, it is important to tick the Media option as shown:
Setting a data object as media type means that it gets a special semantic by having a URL and allows streaming etc. This then sets the property hasStream to true in the service document as can be seen when issuing a $metadata request to the service:
Furthermore in the model provider class <classname>_MPC this line of code is dynamically added: lo_entity_type->set_is_media(‘X’ ).
For a further description of the Media property see also: http://help.sap.com/saphelp_gateway20sp04/helpdata/en/67/d2c38221984d8eb46b8a8d983407b9/content.htm
Lastly an entity set based on the entity needs to be created,
4. Create Upload Service
To create the actual service simply look in the “Service Implementation” folder and right click the “Create” operation and select “Map to Data Source”. Select the function module you use for uploading files. Do the same for the “GetEntity (Read)” operation but of course based on the download RFC. Use the “Propose Mapping” functionality to map the parameters. You should end up with mappings similar to this:
For the services to work some manual coding also needs to be done. This is done through redefinitions of the standard methods on the classes <classname>DPC_EXT and <classname>MPC_EXT. You locate these in the “Runtime Artifacts” folder. They are opened by right clicking them and choosing “Go to ABAP Workbench”. The methods are then redefined by right clicking them and choosing “Redefine” – all pretty simple 😉
A total of three redefinitions was done and I will describe them below:
A – Marking Mime Type
When entity type has been marked as media (as described in step 3) we also have to mark which of the entity properties that holds the mime type of the object. This needs to be done programmatically by redefining the method DEFINE of the model provider class <classname>_MPC_EXT.
Code is inserted to mark one of the entity type properties as Content type i.e. the property that represents mime type information. You can get the the code snippet that you can adapt to your case here SAP NetWeaver Gateway Service Builder: How to Read Photo – Code Snippets which is from Rashmi BR excellent blog that you can find here How to Read Photo from SAP system using SAP Gateway
B – Redefining CREATE_STREAM
To support the upload of files the method CREATE_STREAM needs to be redefined in class <classname>_DPC_EXT. All the needed parameters are available in the redefined method. First the filename or other key parameter can be retrieved through import parameter iv_slug:
The actual uploaded media and mime type parameter is contained in import parameter is_media_resource:
GET_ENTITY is the used to perform a read and then the parameters can be copied to the request through standard method COPY_DATA_TO_REF :
20140127 Updated code below to perform correct read after upload.
C – Redefining GET_STREAM
To support the downloading of files the method GET_STREAM needs to be redefined in class <classname>_DPC_EXT. All the needed parameters are already available here. First the key parameters are retrieved. In example below it is “Pernr” that is retrieved but “Filename” is also retrieved the same way as it is part of the key in this example:
Then the file download is requested and the stream and mime type is copied to export parameter using standard data type ty_s_media_resouce through standard method COPY_DATA_TO_REF:
6. Running the Services
To test the Create and Read services the following calls can be executed:
A – Create
To run my example you perform a HTTP POST to a URL like this: host:port/sap/opu/odata/sap/<servicename>/Files
You can use the built in Gateway Client tool to test the service. You execute the client tool from /iwfnd/maint_service and then in the tool you can use the “Add File” button to add a file to the POST request and the + button to add headers to the post request.
In the post command you need to add the headers “Content-Type” and “slug”. For example for PDFs content type should be “application/pdf” and slug needs to contain the key – in my case filename. Note that if you use Gateway client tool you don’t have to supply content type parameter.
NOTE: If you are not using the Gateway client test tool you also need to remember to add the X-CSRF-Token in the header of the post command. You can get the token by issuing a GET to the service with the header=x-csrf-token and value=fetch. You will then be able to read the token in the response and can supply it in the POST.
On successful POST the document is stored in the database table and you get some xml response back.
PROBLEM: in my response I’m missing the keys of the just uploaded document as shown below. So I guess I’m doing something wrong in my implementation of CREATE_STREAM as described in 5.C. Has anyone got some hints for me to solve this?
Note that in my example the Personnel number and creation Date are automatically retrieved by the service implementation so doesn’t need to be supplied in the post.
B – Read
To read information about the uploaded files a GET containing the keys – in my case “Pernr” and “Filename” – can
be issued like this: host:port/sap/opu/odata/sap/<servicename>/Files(Pernr='<pernr>’,Filename='<filename>‘)
In the response you will then be able to see that the actual document can be retrieved/downloaded by adding /$value to the request above for example:
I have written these services to the best of my knowledge but I’m very interested in getting feedback and possible improvement points.