Uploading Files to SAP GW, Downloading Files from SAP GW – New Techniques
Introduction
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. 🙂
New techniques
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
Remarks
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.
Hi Peter,
Great post about this - ironically I'm just debugging what I believe is a Gateway bug with attaching via a navigation entityset you mention above.
So for reference, it seems if you have attachments in one service, and reuse that service in another service, when you try to post an attachment via a navigation - then it doesn't work saying it can't find the entity that you are navigating through ("Data object '<entity>' not found."). Works fine if both entitysets are in the same service.
Anyway, will update when I solve it just in case anyone else wants to build a reusable Attachments service to include in other services.
Thanks for posting and the mention,
Matt
Hi Matt,
thanks for comment and initial idea, let's see how your issue will be solved
Best regards,
Peter
Hi Peter,
Bad result unfortunately, SAP have stated that Post to another service (stream or otherwise) is not supported. Hence if you wanted to create a reusable attachment service and use navigation to post directly to it without having to move properties around; then it would not be possible.
That said, I think SAP should address this ASAP (refer to my answer in Posting through a Navigation to an EntitySet in External Model Reference Bug?).
Cheers,
Matt
Hi Peter,
first i want to thank for the great post, which is very useful.
i'm facing an issue while following the above process because in my scenario i'm creating RFC(Function modules & table in ECC-Backend) and i'm creating oData service in Netweaver Gateway-Frontend.
So according to my scenario i followed your post & How To Upload and Download Files Using SAP NW Gateway SP06
By Using both the Post I'm able to Display Image(Get Stream method is working fine) But i'm facing on issue While Uploading Image(Problem is with Create Stream Method).
i have followed the code snippet for Display Image Its working fine.
SAP NetWeaver Gateway Service Builder: How to Read Photo - Code Snippets
Here I'm Calling Get_Entity Method for displaying image instead of calling RFC In your code
But i didn't find code for Create Stream there. so at that time your post helped me a lot so i thought of using your idea and call Create_Entity method instead your calling RFC Directly.
So for that im calling Create_Entity method in Create_Stream method.
But while calling the method its going into Exception.
My Question is.
1. Is it the correct way to do?
2. If correct can i pass IO_DATA_PROVIDER or Not
3. If i don't pass the data also its going into Error & If I pass also its going into exception.
For this i have followed another way i have copied code from Create_Entity method and passing the value here manually.I dont think this is correct way to do it.
Now the Image is uploading in Table but in showing an error in Gateway Client.
<?xml version="1.0" encoding="utf-8" ?>
- <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code>005056A509B11ED1B9BF9F46AA8E82ED</code>
<message xml:lang="en">In the context of Data Services an unknown internal server error occured</message>
- <innererror xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<transactionid>558586FF9F09249BE1000000AC190A66</transactionid>
<timestamp>20150623095848.9848970</timestamp>
- <Error_Resolution>
<SAP_Transaction>Run transaction /IWFND/ERROR_LOG on SAP NW Gateway hub system and search for entries with the timestamp above for more details</SAP_Transaction>
<SAP_Note>See SAP Note 1797736 for error analysis (https://service.sap.com/sap/support/notes/1797736)</SAP_Note>
</Error_Resolution>
</innererror>
</error>
Any suggestions are highly appreciable.
Thanks & Regards,
Santhosh Reddy.
Santhosh,
Sending any output to response payload? Like when you created SO - SO Created successfully with 20103400.
Just try with send some output to browser.
Thanks,
Syam
Hi Shyam,
I'm not sending any response but it should not display any error in my case if the error is there or it should not upload a image,
like while creating a SO if that is success then only you will get SO Created successfully with 20102211 or else it will show Error and it will not create any SO.
In my case Error is also there and SO is also creating??
Regards,
Santhosh
Ya... try to send some output to response payload(Fill atleast on filed in ER_ENTITY) once upload done the successfully .
Thanks,
Syam
But when try to call Create_Entity method its giving exception for that reason i have copied all the code from Create_Entity and using here and i dont have option to pass field in ER_ENTITY
ER_ENTITY-mimetype = im_mimetype.
Try like above.
Hi Peter,
Excellent Blog.
I will try with same scenrio and let you know .
Thanks,
Syam
Hi Syam,
thanks for testing, I have also added screenshot from gateway client.
Best regards,
Peter
Hello Peter,
Great
Thanks you for sharing the information.
Regards,
Ashwin
Hi Ashwin,
you are welcome.
Peter
Hello Peter,
Awesome blog, need to try this...
Regards,
Vijay V
Hi Vijay,
let me know if you experience some problems.
Peter
Hi Peter,
This is a neat service, I just have a comment to add about section 5.
In terms of writing a simple service for demonstration, storing the image to a DB is OK, but should be avoided at all costs for any productive use.
Binary content should really be stored via one of the mechanisms that allows it to be placed in a dedicated repository that won't impact the central system of record by eating up its space.
Have a look at this post: ArchiveLink: Uploading Employee Photos
I've used that method to integrate GW service with SAP standard backend rather than using a custom storage solution. Maybe you could refactor your implementation to do something more along these lines? It's a lot better when you see your efforts turn up in standard application space!
Cheers
Ron.
Hi Ron,
thank you for your valuable suggestion. I will try to prepare modified solution.
Best regards,
Peter
Hi Peter,
Another gotcha I found today for attachments - If you use the same association to one attachment object, but use a different relationship; within create_stream, the relationship info is blank.
e.g. If you had a relationship against UserSet of EmployeePhotos, which used the same Photo Association; you can't tell within the create_stream method which relationship was used. Working around this by trying to read the relationship out of the URL which is dodgy, but a temporary workaround.
Cheers,
Matt
Hi Matt,
I am a bit confused. I am not sure what you mean by "same association, different relationship". Do you mean the cardinality by relationship? I would have association called Photo1 with different cardinality than association Photo2 and I would not be able to read the association name from input parameters, only from URL. Is this the case?
Thank you,
Peter
Hi Peter,
To explain further, in my examples, I have an association to attachments, and rather than create multiple associations to differentiate which type of attachment I'm uploading, I create multiple navigation values using the same association. e.g. you should see the navigation name, not the association name in the navigation property. Unfortunately, the navigation properties are completely empty; so yes - I use the URL. Associations don't appear in the URL at all; just the navigation name.
Hope that helps, and if you don't have the same requirement, you should be fine.
Cheers,
Matt
Matt,
thank you for explanation, it is clear now. I have got confused about the association/navigation property and its appearance in URL. I will try your scenario as well
Best regards,
Peter
Hi Peter,
Nice blog....
Regards,
Imran.
Hi peter,
Thanks for nice blog, I tried this example but I am getting error in the gateway client as
'Method 'USERSET_GET_ENTITY' not implemented in data provider class' after executing the same URL '/sap/opu/odata/sap/ZSA_FU_SRV/UserSet('vicky.ssap@gmail.com')/Photo' with HTTP parameters slug = image.png as suggested by you
I am bit confused as this example contains redefinition for USERPHOTOSET entityset not for USERSET.
Please provide your comments and help!
Thanks & Regards,
S.Vikgnesh
Hi Vikgnesh,
did you use POST method for sending the file? I guess this could be the issue when you use GET method.
Regards,
Peter
Hi peter,
I just created the same example you provided. But the create_stream method is not triggering and i am getting error as 'Incorrect configuration for profile /SIHTTP/HTTP_DOWNLOAD' in the gateway client.
Could you please help?
Hi Vikgnesh,
I do not have experience with configuration, could you try to look in discussions, or post question if you do not find answer?
Thanks,
Peter
Hi peter ,
I created the same tables and entity sets as given in your example but at the time of creating association Photo is not automatically coming under the navigation property for user so i created the same.
but when i click on generate run time object button it shows the following error message.
so can you please help me with this issue.
Thanks,
Anshul D
Hi Anshul,
Which ever the key parameters you are mentioning in the first entity, that needs to be mapped with dependent entity.
Suppose my first entity has key parameter Email, then my second entity should also be the same, so that I can map the same in the referential constraints.
Suppose my first entity has key parameter Phone number, then my second entity should also be the same, so that I can map the same in the referential constraints.
Thanks,
Vijay V
Hi Anshul,
did you managed to solve it based on Vijay answer?
Regards,
Peter
Hi Peter,
Yeah the problem has been solved.
Now the problem is coming in the service URL when i try to run the service url in the web browser its showing "Data Oobject 'UserPhoto' not found." and I am not getting where the problem is occurring. So it would be great if you can help me with this error.
Thanks and regards,
Anshul D
Hi Anshul,
Firstly check whether you are passing Entity set or Entity in your URI, and also remember that it is case sensitive.
We need to pass Entity set name in the URI
your_service/UserSet('usermail')/Photo
Thanks,
Vijay V
hi Vijay ,
Thanks for the reply I am giving entity set name only and its showing the message like this
"Resource not found for the segment 'UserSet('anshul.dharmadhikari@gmail.com')".
can you help me with this.
Thanks
Anshul D
Hello Anshul,
The error is because in your URL :
1. You might be using a property which is not at all in your data model.
OR
2. You might be using in an incorrect way.
URL would be,
/sap/opu/odata/sap/ZSA_FU_SRV/UserSet('vicky.ssap@gmail.com')/Photo'
where,
UserSet is the EntitySet name & Photo is the Navigation property.
Please cross check your URL again.
Regards,
Ashwin
Hi Anshul,
Check whether your entity is defined as Media and see the Associations screenshot correctly and also check your all the above mentioned MPC and DPC methods implemented.
Vijay V
Hi Vijay,
Thanks again .
Can you please tell me how to upload image at the time of post request using gateway client.
Thanks
Anshul D
Hi Anshul,
Step 1: your URI
Step 2: Request Headers :
Content-Type : image/png
slug : here you can pass your input parameters(Phonenumber_Emailid)
98989898_anshul@gmail.com
Step 3:Click on add the file and add the image.
Write the split statement in your code and split accordingly and pass it to the respective fields.
Vijay V
Hi Vijay,
thanks for your help.
i checked everything from url to all the methods and all are working properly but now the error shown in the gateway client is
"No default virus profile active or found. Please check the offical guide."
So do you know what is this.
Thanks
Anshul D
Hello Anshul,
U need to define the virus profile. Your BASIS Team can help doing this.
Regards,
Ashwin
Hi Anshul,
As Ashwin said,deactivate the Virus scan profile, you can also use the transaction /IWFND/VIRUS_SCAN.
You will be able to see the output.
Vijay V
thanks Vijay and Ashwin,
Its working now, thanks a lot for helping me out.
regards
Anshul D
I have same problem. I configured VSCANPROFILE but the result is wrong:
<message xml:lang="en">Incorrect configuration for profile /SMIM_API/PUT</message>


Could you share your config ?
Thanks.
Does anybody tried with upload/download files using SAP DMS
Hi Syam,
Can i use odata service to store files into DMS server ?
Hi Sanoop,
Yes u can use...
Vijay
Hi Sanoop,
Yes we can upload/download the files from DMS using odata/ui5.
Thanks,
Syam
hi syam,
i have created a service for uploading and downloading files through neteweaver
gateway. i use SAP database for storing files in binary form. But i want store the files directly to SAP system and expose it through OData/ui5.
i am new to odata service and how can i achieve this.??
Thanks in advance.
Sanoop PS
What approach have you taken to upload/download photos to/from DMS via UI5? I am facing a similar problem.
Hi Peter,
Nice blog with good description in simplified language. Easy for beginners to understand and practice.
Aashika
Hi Aashika,
thank you for kind words, I really appreciate that.
Peter
Hi Peter,
This is a very helpful blog with different approach to upload/download media files.
I am facing very strange issue, when I redefine DEFINE method from MPC_EXT class, any changes in DATA MODEL after that are not reflected in metadata. I have explicitly clean up cache using /IWFND/CACHE_CLEANUP in backend system and then changes are getting reflected.
This is happening for every project.
When I removed the redefinition of DEFINE method, changes were reflecting right away.
Can you suggest any solution?
Any help would be immensely appreciated.
Thanks in advance!
Shefali
Hi Shefali,
Yes.Here we have understand When changes done from Model it will reflect to MPC/DPC classes only.once project generated successfully we have to redefine the particular method based on the model and service implementation.
Thanks,
Syam
Hi Peter,
Thank you for sharing valuable info..
I'm struggling when create file in service.
Please check and help me.
This is my Entity type and Entity set in my service.
This is my DEFINE method.
And here is my create_stream method.
So when i add selected service I'm getting this warning.
And when click on EntitySets, displays this information message.
Problem there is in DEFINE method i guess.
How can i resolve it.?
Thanks,
Siva R.
Hi Siva,
sorry for late answer. I can't see anything wrong with your entity. Can you please post your question as a discussion topic? More people will notice it.
Best regards,
Peter
Hi Peter,
Got it, thanks for your response.
Regards,
Siva R.
Hello Siva,
See in the GW Model the property defined is ' FileName' and in the Define method your are trying to get the property ' MIMETYPE' which not available in your Model at all and you are bound to get error saying Metadata cannot be loaded.
Instead of MIMETYPE in define method use FILENAME. It should work.
Regards,
Ashwin
Hi Ashwin,
Working fine.... Thanks a lot..!
Best Reagrds,
Siva R
HI,
Thanks for the nice blog, but when I tried to replicate the scenario I am getting an error. "No valid source context supplied". could you please throw some light.
Thanks
Anversha
Resolved the issue - Just want to share the experience.
Always provide "Entity Type" name in create stream and read stream case statements. Don't mention the entity set name. Beginners may have a tendency to give this and stuck.
Any virus scan error contact basis team and inform them to maintain default profile.
Anversha
Hi,
It's a nice blog, I have one question - 'Is it possible to include multiple CREATE_STREAM calls in one batch call ? ' basically I what would like to upload multiple images through a batch call (which should trigger multiple calls to 'CREATE_STREAM' method ). Is this possible ?
Regards,
Chandrashekhar
Hi Peter,
I am trying to upload a file and facing some issue for which i have posted a discussion.
Below is the link for the same. Kindly Help.
Thanks in advcance,
Samir
Thanks for the nice document.
Hi,
i have created a service to upload and download files.
I am getting "CSRF token validation failed" error in response. X-CSRF token parameter is in disabled mode in my SAP system. I can upload files with this service in SAP Netweaver Client transaction but it doesn't work when i call this from UI5 application.
Should we need X-CSRF token to execute this process?
i am getting below error,
POST http://localhost:53044/ZFILE_UPLOAD/proxy/sap/opu/odata/sap/z_issuelog_appl_srv/ZilogDetailsSet('IL00000380')/ZilogAttachmentSet 403 (Forbidden)
Kindly help me to solve this.
Thanks,
Ranjani Sekar,
Hi Ranjani,
IF CSRF Token is enabled in your system then for every POST Method you have to Pass the CSRF Token.
For getting the CSRF Token you have to execute a GET method with the CSRF Token set to "Fetch" and pass the Same while doing the POST Method.
Regard's,
Samir
Yes.You have to follow Samir steps for Fetching CSRF Token.
Thanks,
Syam
Hi,
Thanks for the blog, i have tried to follow the steps given above, able to post the image.
But when i try to use GET i get this error,
I am using the get method with this paramater
/sap/opu/odata/sap/ZMEDIA_SRV/UserPhotoSet('sss@gmail.com')/$value
Resource not found for segment 'UserPhoto'
Kindly help me to solve this.
Hi Shobha,
Have you set the UserPhoto entity type as a Media
Thanks,
Syam
Hi Syam,
Yes i have marked it as Media.
Hi Shobha,
Did you set the Mime type in the "Define" Method of *_MPC_EXT class?
Please create a implementation of the Define Method in *_MPC_EXT class as below :
super->define( ).
DATA:
lo_entity TYPE REF TO /iwbep/if_mgw_odata_entity_typ,
lo_property TYPE REF TO /iwbep/if_mgw_odata_property.
lo_entity = model->get_entity_type( iv_entity_name = Enity Type name of attachment Entity ).
IF lo_entity IS BOUND.
lo_property = lo_entity->get_property( iv_property_name = Field name of Mime Type ).
lo_property->set_as_content_type( ).
ENDIF.
Hi Samir,
Thanks, but I already defined DEFINE.
lo_entity = model->get_entity_type( iv_entity_name = 'UserPhoto' ).
IF lo_entity IS BOUND.
lo_property = lo_entity->get_property( iv_property_name = 'Mimetype' ).
lo_property->set_as_content_type( ).
ENDIF.
Hi Shobha,
Have you called the define method of the super class as :
super->define( ).
Also can you let me know the what is the entity set name?
Also attach the screen shot of you GW client window with the error.
Hi Samir,
me entity set name is User and UserPhoto,Please see my screenshot in above post.
below is the error.
also, here is the data i have in my db, i succesfully done the post, but not able to get back data.
Hi all,
I have got the output image now.Implemented method Read stream.
The call is not coming to GET STREAM method so tried to do with the READ STREAM method to resolve the issue.
Thankyou guys for having time.
Hi syam,
worked with read stream method. Thanks!
Ok..Good
Thanks,
Syam
Hello,
I am facing issue while post operation ..
I have started new discussion for the same>> Here <<
Thanks
PavanG
Hi Peter,
Nice article .
I am not able to POST Photo to server. I am getting Resource not found.
Please correct me.
Thanks,
Great blog! I have implemented this on SAP Notes downloading. But recently I encountered a problem. If the response time is too long, i.e. the file is too big, then the connection will be closed. The file thus cannot be downloaded.
Is there any solution to this?
Thanks and best regards,
Alex
Awesome post! Txs!
Hi Peter,
Great Job!!!!
I am looking for exactly same scenario ,it helped to achieve my requirement.
thank you very much.
Thanks,
Naveen
Hi Peter,
Thanks for the wonderful blog!! Was able to develop a sample service.
If we need to send the POST & READ requests in JSON then what should the request be like in this case? Tried the usual "$format-json" but that does not work.
Any ideas? Not sure if this is possible.
regards
Nitesh
Hi Peter,
Great blog and still relevant!
I think perhaps it is worth mentioning that in newer "Service with Vocabulary-Based Annotations" (as opposed to the default "Service with SAP Annotations") one no longer has the "Media" checkbox against the Entity Type in the Service Builder UI.
In this case you have to flag the entity type as being media in the model's DEFINE method override:
Cheers,
Francois.