Handling attachments in IE9 & Older version browsers from SAPUI5 application and uploading them to SAP via SAP Gateway RESTful services
- added SAP Note 2170724 to fix error when maintaining external aliases
Use case: We need to upload the attachments from IE8/IE9 browser using SAP Gateway and SAPUI5. Many Enterprises still love to use legacy (old) browsers. 😆
So enabling these functionality becomes critical for companies without doing major browser upgrade. Let’s get started by discussing the scenarios and subsequently explaining the solutions involved.
Problem statement: SAPUI5 File uploader will work only with modern HTML5 browsers when using SAP Gateway as a backend to store files.
Issue: SAP Gateway OData service requires 2 custom headers to be set when handling attachment. (X-CSRF-Token and Slug). Only HTML5 compatible browsers will support setting these custom HTTP headers! In other words setting HTTP headers for a file upload request will not work in IE8 and IE9.
1.If you are using any Java server as frontend then below fix could be useful for you as suggested by W.Snoep ( Thank you Wim)
“Send parameters in the URL, and use the servlet to add the header parameters based on the URL parameters. The servlet already had the functionality of proxying but now also use it, to add the proper headers for slug and x-csrf/ x-requested-with header. This works and does add the file in the backend. However, since IE9 sends the file via an iframe as multipart/form data, it has extra header and footer data in the file in the backend. These need to be cut off in the backend ECC system. This functionality works smoothly now for IE9.”
2.If we can’t solve using (1) then we can follow below approach. (When both our frontend & backend are SAP systems).
Create a custom handler to achieve this.This blog mainly focuses on this approach. Here are the steps involved.
The development activities for this scenario have been split into two steps:
- Creation of custom handler – Setting up the Gateway environment (Steps covered in this blog)
- Consuming the OData service from SAPUI5 application (Watch out for this in the next blog)
Creation of custom handler – Setting up the Gateway environment
Client side (UI5 ver 1.22.4):
– In the UI5 client, for IE8 and IE9, add the x-csrf-token and slug (if you need it) value as hidden input value to the upload form. For newer browser (Chrome, IE10 etc.) , these values are added to the http request header.
– You can look up how to retrieve the upload form by looking at the upload method implementation for the FileUploader control in UI5 source code.
– For IE8 and IE9, set a different value (external alias defined below) for the uploadurl attribute of the fileuploader control.
The problem for IE8 and IE9 is that the default handler class (/IWFND/CL_SODATA_HTTP_HANDLER) for ICF odata node only reads the x-csrf-token from the http header and it’s not possible to set http header in IE8 and IE9. The idea is to create a custom handler to read the x-csrf-token from the post data and add it to the http request header and resume the normal request flow.
– Create a new custom handler class that implements the interface IF_HTTP_EXTENSION. This handler will read the x-csrf-token (or whatever name you use for the hidden input field) and set it in the http request header
– Since we cannot modify the handler list for the odata node because it’s sap standard, we’ll add the custom handler to the handler list in our application node which we have control. Add the default odata handler (/IWFND/CL_SODATA_HTTP_HANDLER) as the next handler in the list.
– Create an external alias for the new custom handler (e.g. customhandler). This value is used as the value for the uploadurl attribute on fileuploader control (pre-pend and append the value with ‘/’, e.g. /customhandler/) before setting to uploadurl attribute.
In IE8 and IE9, the fileuploader uploadurl will point directly to the application node and our custom handler will be processed before the default odata handler. Our custom handler reads the x-csrf-token from the post data and sets it to the http request handler thus allowing the default odata handler to read it.
Let’s start with coding and configuration stuffs. Assume we have created an OData service to handle attachments. Please refer below blogs if you want to know more on this.
Once we are done with the service you can notice our service will have a corresponding entry in the ICF application. Go to TCode SICF and check as shown below.
Click on the above highlighted entry and you can see the handlers involved.
The above handler will check the consistency of the X-CSRF-Token at runtime when we upload a file.
Now we need to manually set the X-CSRF-Token by creating a custom handler.
This must implement the interface “IF_HTTP_EXTENSION” and write logic in the method “IF_HTTP_EXTENSION~HANDLE_REQUEST” This will read the x-csrf-token and set it in the http request header
DATA: token TYPE STRING,
slug TYPE string.
*Read the Cross site forgetory token and Slug parameter from the POST data…
token = server->request->GET_FORM_FIELD( name = ‘X-CSRF-Token’).
slug = server->request->GET_FORM_FIELD( name = ‘Slug’).
server->request->set_header_field( name = ‘X-CSRF-Token’ value = token ).
server->request->set_header_field( name = ‘Slug’ value = slug ).
me->if_http_extension~lifetime_rc = if_http_extension=>co_lifetime_keep.
*Add below code so that subsequent handlers are called for the application node
me->if_http_extension~flow_rc = if_http_extension=>CO_FLOW_OK_OTHERS_OPT.
After done with creation of custom handler then we need to assign this to our OData service in the SICF application node as shown here.
Create an external alias for the new custom handler. This value is used as the value for the uploadurl attribute on file uploader control in the SAPUI5 app.
Click “External Aliases” and create a new alias pointing to our OData service we created in the beginning.
Make sure you prepend the alias name with forward slash ‘/’ otherwise you might encounter some error. After successful assignment alias structure will be like below one.
When maintaining external alias if you get error “Service not found” implement below note to sort this out.
2170724 – Call of external aliases terminates with error text “Service not found”
Test the alias:
Testing the application:
For testing purposes I am using Google chrome to simulate IE behavior and check whether our OData service is working by passing data in URL headers. (Instead of passing in HTTP headers).
Get the X-CSRF-Token first:
Now get the token from the above request and pass them as URL parameter. Do not pass them in HTTP header .Use below URL to POST data to the server. Also attach the file which you want to upload. So our request should look similar to this.
Ensure we call in the below format:
AliasName – External Alias which we created pointing to OData service
EntitySetname – OData service Entity which handle media stream. In our case it is ‘FileDetailSet’
Slug – This can be used to pass File name, File type, File length etc.
Once we hit “Send “we can see below how the flow will happen in ABAP system.
Set the HTTP header manually in our custom handler which will be triggered first before calling OData handler.
As a next step our OData handler will be triggered. We can verify whether it is validated correctly in the Gateway framework as shown below (Flag set to X).
Finally we can see our create stream method is triggered. /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_STREAM
File content and Slug parameters are retrieved successfully within the Gateway framework.
Many Thanks to Andrew Ng for proposing this solution which motivated me to write up this as a blog. In my next follow up I will illustrate how we can integrate this to a SAPUI5 app and execute this from a MSIE (IE9) browser.
Thanks for reading this. Appreciate your feedback ! Also please hit “Like” if you like the blog post.
Thank you Brian !
Good Blog ! Well done Prabaharan Asokan !
Thank you chandra.
Could you please help me in sharing this blog to SAPUI5 forum ? I believe this could be helpful to SAPUI5 community as well. Thanks for the help.
-- Prabaharan Asokan
Sure. You can CC SAPUI5 Developer Center
Thanks Chandra. I have added the SAPUI5 link to the blog content.
Very useful blog !
Nice you wrote your findings down into this blog.
Regarding solution 1. This is actually also using SAP for frontend and backend. Only in this case we have a SAP Java stack as intermediate proxy, and fixed the issue here.
Regarding solution 2. Nicely written down. Another way of doing the same: transforming parameters into headers because of the iframe fallback. Don't you have the issue of extra headers and footers in your file content because of multipart data?
Thank you for the appreciation and comments. I am still working in SAPUI5 part. Once I am done with it I will let you know the details.
Were you able to remove the header and footer from the attachment content? Please share your findings and resolution.
I am working on it. Will update the details soon. Thanks
Just to share:
1. I raised a message to SAP with the statement/question:
"The issue is that when using sap.ui.commons.fileuploader in IE9, the attachment content contains header and footer. The header and footer gets uploaded as part of the file resulting to extra characters when the file is downloaded. Is there a standard solution to attach file in IE9 using UI5?"
And the reply I got was:
"As Internet Explorer cannot handle XHR requests it switches back to a form submit which has these generated header and footer parameters. Therefore Chrome and Firefox work fine and the issue only occurs in Internet Explorer 9 and below. So we can't provide a better solution than what you already suggested.
2. I found a solution to remove the header and footer characters from the attachment content by string and xstring manipulation. Here's how I did it:
a. Convert XSTRING to STRING. The header will contain the text below. And I convert and cut the content value based on this.
content-disposition: form-data; name="fileUploader"; ....
b. Footer will also have "content-disposition: form-data" in the text. Look for this text in the XSTRING and split.
Could you please share your findings in UI5 as a blog( a humble request ) ? This would be useful to community members as well as me 🙂 . Also add the content to delete header & footer details.
I'm running into an issue when stripping out the header and footer, the file is getting corrupted when trying to run it after that process. This works fine for text and PDF documents but not MS Word, Excel, or images. Any other tips?
Thanks in advance,
Thank you for writing this excellent blog!
Thank you Andrew !
I've implemented it but getting the following error,
'Unable to create attachment'
I see an HTTP 400 error. I'm using the TaskProcessing service and Unified uploader.