Skip to Content

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.

entity_users.JPG

/wp-content/uploads/2014/07/table_users_505591.jpg

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.

entities.JPG

entity_photos.JPG

table_photos.JPG

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 Re: How to send additional parameters with file upload by Matt. Now you can see why it is good to follow discussion 🙂

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.

assocations.JPG

constraints.JPG

Now, there should be a navigation property in User entity called Photo:

datamodel.JPG

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

gw1.JPG

GET method: your_service/UserPhotoSet(‘usermail’)/$value

gw2.JPG

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.


To report this post you need to login first.

80 Comments

You must be Logged on to comment or reply to a post.

  1. Matt Harding

    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

    (0) 
      1. Matt Harding

        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

        (0) 
      2. Santhosh Reddy

        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

         

        error1.PNG

         

        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.

         

        error2.PNG

         

        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.

         


         

        error3.PNG


        Now the Image is uploading in Table but in showing an error in Gateway Client.



        error4.PNG

         

          <?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.


        (0) 
        1. Syam Babu

          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

          (0) 
          1. Santhosh Reddy

            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

            (0) 
            1. Syam Babu

              Ya… try to send some output to response payload(Fill atleast on filed in ER_ENTITY) once upload done the successfully .

               

              Thanks,

              Syam

              (0) 
              1. Santhosh Reddy

                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

                (0) 
  2. Ron Sargeant

    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.

    (1) 
  3. Matt Harding

    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

    (0) 
    1. Peter Marcely Post author

      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

      (0) 
      1. Matt Harding

        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

        (0) 
        1. Peter Marcely Post author

          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

          (0) 
  4. S. Vikgnesh

    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

    (0) 
    1. Peter Marcely Post author

      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

      (0) 
  5. S. Vikgnesh

    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?

    (0) 
    1. Peter Marcely Post author

      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

      (0) 
  6. Anshul Dharmadhikari

    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.error.JPG so can you please help me with this issue.

     

    Thanks,

    Anshul D

    (0) 
    1. Vijay Vegesana

      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

      (0) 
      1. Anshul Dharmadhikari

        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

        (0) 
        1. Vijay Vegesana

          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

          (0) 
            1. Ashwin Dutt R

              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

              (0) 
            2. Vijay Vegesana

              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

              (0) 
                1. Vijay Vegesana

                  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

                  (0) 
                  1. Anshul Dharmadhikari

                    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

                    (0) 
                    1. Vijay Vegesana

                      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

                      (0) 
                        1. thanh vu duy

                          I have same problem. I configured VSCANPROFILE but the result is wrong:

                          <message xml:lang=”en”>Incorrect configuration for profile /SMIM_API/PUT</message>/wp-content/uploads/2015/10/2015_10_07_9_15_13_804450.png/wp-content/uploads/2015/10/2015_10_07_9_16_38_804451.png/wp-content/uploads/2015/10/2015_10_07_9_17_24_804470.png

                          Could you share your config ?

                          Thanks.

                          (0) 
        1. SANOOP P S

          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

          (0) 
  7. Shefali Chopkar

    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

    (0) 
    1. Syam Babu

      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

      (0) 
  8. Siva prasad Ramani

    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.

     

    /wp-content/uploads/2015/02/q1_637884.png

    This is my DEFINE method.

     

    /wp-content/uploads/2015/02/q2_637889.png

    And here is my create_stream method.

    /wp-content/uploads/2015/02/q3_637890.png

    So when i add selected service I’m getting this warning.

    /wp-content/uploads/2015/02/q4_637891.png

    And when click on EntitySets, displays this information message.

    /wp-content/uploads/2015/02/q5_637896.png

    Problem there is in DEFINE method i guess.

    How can i resolve it.?

     

    Thanks,

    Siva R.

    (0) 
    1. Peter Marcely Post author

      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

      (0) 
    2. Ashwin Dutt 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

      (0) 
  9. Anversha s

    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

    (0) 
  10. Anversha s

    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

    (0) 
  11. Chandrashekhargouda Danappagoudar

    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

    (0) 
  12. Ranjani Sekar

    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,

    (0) 
    1. Samir Shaikh

      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

      (0) 
  13. Shobha Devi Gokaraju

    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.

    (0) 
        1. Samir Shaikh

          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.

          (0) 
          1. Shobha Devi Gokaraju

            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.

            (0) 
            1. Samir Shaikh

              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.

              (0) 
              1. Shobha Devi Gokaraju

                Hi Samir,

                me entity set name is User and UserPhoto,Please see my screenshot in above post.

                below is the error.

                error.JPG

                also, here is the data i have in my db, i succesfully done the post, but not able to get back data.


                Capture.JPG

                (0) 
              2. Shobha Devi Gokaraju

                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.

                (0) 
  14. Alex Dong

    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

    (0) 
  15. Nitesh Jain

    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

    (0) 

Leave a Reply