Recently, I had time to revise my solution for uploading and downloading files using SAP gateway. I discovered some new techniques and improvements mainly here in SCN, I would like to share with you solution based on these findings. So thanks for all contributions and I hope I mentioned them all here in this blog post.
Most credits go to Jan Thomas Nygaard for his blog post How To Upload and Download Files Using SAP NW Gateway SP06 which became my most used bookmark in browser. 🙂
These are the techniques I would like to share:
- code based implementation
- using two entities, separation of media and non-media data
- sending key parameters to media entity through navigation property
- storing XSTRING in SAP
- supplying file name in response for browser
Steps to get it done
1. Code based implementation
Based on How to Develop a Gateway Service using Code based Implementation, I wrote blog post how to create project called ZSA_USERS and how to prepare entity User which can be accessed via oData service and can handle operations CREATE, GET, PUT, DELETE also with code snippets. So this is a prerequisite before we continue with creating media entity.
2. Two entity – creating media entity
In order to avoid sending too many parameters (via header parameters or slug header) into Media entity during file upload, let’s divide entities. As in the example non-media entity stores all data about user, while media entity stores all relevant file data. This approach is based on suggestion by Ron in following discussion How to pass arguements to CREATE_STREAM?
Entity User is backed by db table zsa_users.
Now same way as we created entity user, we are going to create entity UserPhoto. UserPhoto is backed by db table zsa_photos. Do not forget to set UserPhoto as media collection.
Also do not forget to (re)generate runtime objects, rather more time than never.
3. Creating association between entities
The reason behind this approach is that it is not possible to access to the key parameters when uploading file in CREATE_STREAM method. Thus, there are a workaround using slug HTTP header or custom HTTP headers to supply the key parameters. My former solution was implemented this way, but I reworked it as following. Again, this suggestion came from discussion Matt. Now you can see why it is good to follow discussion 🙂by
Now let’s create Associations between User and UserPhoto, cardinatily needs to be 1…N. (1…1 did not work for me, thanks to Krishna for helping me figure that out). I used email as a key in both cases so lets connect them by this key.
Now, there should be a navigation property in User entity called Photo:
This enables us to post file to UserPhoto entity via User entity where we can supply key parameters! It means that after call like this /sap/opu/odata/SAP/ZSA_USERS_SRV/UserSet(‘john(at)doe.com’)/Photo, it_key_tabs will be filled with key email and its value john(at)doe.com.
Again regenerate runtime objects.
4. Redefine USERS_MPC_EXT->define method
This is important step unless you want to get error message “Invalid or no mapping to system data types found” from Gateway. You need to specify mimetype property of your media set. See document with code snippets with implementation. Code snippets for Uploading Files to SAP GW, Downloading Files from SAP GW – New Techniques
5. Redefine CREATE_STREAM and GET_STREAM methods in USERS_DPC_EXT class
You can find those under inherited methods from interface /IWBEP/IF_MGW_APPL_SRV_RUNTIME. Again, check document with code snippets for implementation. Code snippets for Uploading Files to SAP GW, Downloading Files from SAP GW – New Techniques
I just want to explain some pieces:
- In order to store XSTRING in SAP, I used DB. According to SAP help, it is possible to store it as rawstring. It is not physically stored in DB, only the reference is. There are several limitations for rawstring and I am not sure how much is the performance affected. Other solution is written in my personal blog post using FM ‘SO_DOCUMENT_INSERT_API1’, there should be also maybe nicer way how to do it with GOS.
- supplying file name in response for browser in described in my other blog post Recognizing file name and type in browser after downloading file from Netweaver Gateway. If we don’t supply Content-Disposition HTTP response header, browser may see our file with name ‘$value’ which is definitely not wanted.
6. Post your file to GW and download it back
Now we should be able to test the solution in SAP Gateway client using these URIs. In order to set file name of the photo, we need to add it as http header slug parameter, since it is expected in my CREATE_STREAM implementation.
POST method: your_service/UserSet(‘usermail’)/Photo
GET method: your_service/UserPhotoSet(‘usermail’)/$value
Once again, thanks go to all contributors mentioned in this blog and also those whom I forgot. Please feel free to comment anything that you find wrong, missing or can be improved. I am looking forward to your feedback, as usual 🙂
There is no error handling in the code snippets, take this as a starting point for your implementation.
If you are interested in the how I used this service in UI5 frontend part, you can see my other blog post Upload Image to SAP Gateway and Display Image in UI5 – Using New Fileuploader with SAP Gateway.