cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Need to replicate short php code in BSP

Former Member
0 Likes
1,553

HI All,

First off I know nothing about BSP, just thought I would get that one out the way.

With that said I have tried to follow this wiki :- http://wiki.sdn.sap.com/wiki/display/BSP/Handling+Binary+Data with some success.

Now what I am trying to achieve is simply reproduce this small piece of php code :-

<?php

header("Content-type: application/octet-stream");

header("Content-Disposition: attachment; filename=\"my-data.csv\"");

$data=stripcslashes($_REQUEST['csv_text']);

echo $data;

?>

in a BSP application.

I have tried the following in the layout tab and in the Event OnInitialization:-

<%

   IF request->get_form_field( 'csv_text' ) IS NOT INITIAL.

      response->set_header_field( name = 'Content-Type'        value = 'application/octetstream' ).

      response->set_header_field( name = 'Content-Disposition' value = 'attachment; filename=csv_text.csv' ).

      response->set_header_field( name = 'Connection'          value = 'close' ).

       DATA: file_content TYPE string. file_content = request->get_form_field( 'csv_text' ).

      response->set_header_field( name = 'Expires'       value = '0' ).

      response->set_header_field( name = 'Pragma'        value = 'no-cache' ).

      response->set_header_field( name = 'Cache-Control' value = 'max-age=0' ).

      REPLACE ALL OCCURRENCES OF ' ' IN file_content WITH ''.

      response->set_cdata( file_content ).

      RETURN.

   ENDIF.

%>

The only problem is that I get the desired download dialog box but I am directed to a blank BSP screen with "Your request is being processed" message instead of simply leaving me on my current page and showing a download dialog like with PHP.

I am POSTING some CSV data from a table page in SAP BW to this BSP application that I want to download as a CSV text file.

I can't simply use the export to CSV function of SAP BW because of the modifications I have made in javascript to change the tables.

I am utilising this piece http://www.kunalbabre.com/projects/table2CSV.php  of jQuery utility to get what I require from the client side.  Option 3.1 is what I am trying to achieve.

Any help please?

Thanks

Craig

View Entire Topic
Ruediger_Plantiko
Active Contributor
0 Likes

Hi Craig,

by looking at the code, I don't see an obvious error.

My only concern is about the field Content-Type. I am not sure whether this won't be overwritten by the ICF if you set it with the general set_header_field method. There is a special method set_content_type for it, which I would prefer.

If it still doesn't work: Did you switch on the "Network log" in Firebug (or in MSIE: <F12>), and compared the response headers with your expectations? Which header field values were actually sent in the response?

Regards,

Rüdiger

BTW: Did you know there is an interface IF_HTTP_HEADER_FIELDS containing constants for all specified header field names? Using these constants (like IF_HTTP_HEADER_FIELDS=>CACHE_CONTROL ) instead of literal values may be helpful for avoiding mistyping.

Former Member
0 Likes

Thanks for the response.  I changed the BSP to use set_header_field but have same problem.

Below is the response headers :-

Response Headers

Content-Length    27183

Content-Type    text/html; charset=iso-8859-1

Server    SAP NetWeaver Application Server / ABAP 701

Request Headersview source

Accept    text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Encoding    gzip, deflate

Accept-Language    en-gb,en;q=0.5

Connection    keep-alive

Cookie    sap-usercontext=sap-language=EN; MYSAPSSO2=AjExMDABAAxBUk1TVEVDICAgICACAAMyMDADAAhCV0QgICAgIAQADDIwMTIwNzAyMTMyOAUABAAAAAgGAAFYCQABRf8A9DCB8QYJKoZIhvcNAQcCoIHjMIHgAgEBMQswCQYFKw4DAhoFADALBgkqhkiG9w0BBwExgcAwgb0CAQEwEzAOMQwwCgYDVQQDEwNCV0QCAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTEyMDcwMjEzMjg1N1owIwYJKoZIhvcNAQkEMRYEFKHKk9CO4BE7BO07gr6jG1tal2mBMAkGByqGSM44BAMELjAsAhQPuFOoGUSIqlIrxSFJconeraYWyQIUCawlv5WI48vy06f%2fMrbjnJPL%2f9o%3d

Host    xxxx:8008

Referer    http://xxxx:8008/sap/bw/BEx?SAP-LANGUAGE=EN&PAGENO=3&CMD=PROCESS_VARIABLES&REQUEST_NO=0&CMD=PROCESS_...

User-Agent    Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.1

Response Headers From Cache

Content-Length    27183

Content-Type    text/html; charset=iso-8859-1

Server    SAP NetWeaver Application Server / ABAP 701

Request Headers From Upload Stream

Content-Length    24185

Content-Type    application/x-www-form-urlencoded

Any further suggestions?

Thanks

Craig

Ruediger_Plantiko
Active Contributor
0 Likes

Well, it's difficult to analyze from remote.

But where is the content-type 'application/octet-stream' that you had set?

BTW, shouldn't it be "application/octet-stream" with a hyphen ? In your BSP code, you write 'application/octetstream' without hyphen. 

I don't see the MIME type that you had set in the header field list that you had sent (which is a mix of request and response header fields, anyway).

Did you put a break-point on the ->set_content_type( ... ) statement? Does it reach that statement at all?

Former Member
0 Likes

Lol yes you are correct my mistake I had forgotten the hyphen, but it didn't help anyway.

I have just put a break point on the ->set_content_type but the page is already generated at this point!

It does go through the motions and sets the headers correctly that's when I get the download dialog.

But the page is already generated at this point with the data in it with a form :-

<html>

    <head>

        <style type="text/css">.middle  { vertical-align:middle; }</style>

    </head>

    <body onload="document.forms[0].submit()">

        <form method="post" action="/sap(bD1lbiZjPTIwMA==)/bc/bsp/sap/zsavecsv/savefile.bsp">

        <input type="hidden" name="csv_text" value="&amp;nbsp;,&quot;No Applicable Data Found.&quot;

        &amp;nbsp;,&quot;No Applicable Data Found.&quot;

        &amp;nbsp;,&quot;&amp;nbsp;&quot;

        &amp;nbsp;,&quot;No Applicable Data Found.&quot;

        &amp;nbsp;,&quot;&amp;nbsp;&quot;>

        </form>

            <table border="0" width="100%" height="100%">

                <tr>

                    <td align="center" class="middle">Your request is being processed</td>

                </tr>

            </table>

    </body>

</html>

So it would seem my page  already has a generated html page before my code even kicks in!

Ruediger_Plantiko
Active Contributor
0 Likes

Maybe it's because you are in a page, not in a controller. Probably, the MIME type proposed in the page properties (see screenshot below) will finally be set from the framework.

The more natural approach would be to use a controller or even an SICF request handler for your task. But if you set the MIME type for your page in the page attributes, I don't see why it sholdn't work in your way.

Regards,

Rüdiger

Ruediger_Plantiko
Active Contributor
0 Likes

So you use the same page for two purposes? The download and the form?

Wouldn't it be better to handle the download with a separate item? In particular, since you have different MIME types for the form and the download.

With the "action" attribute of the form page you can specify the controller or page that should take care of the download.

We once had a similar thing (but for uploads), and we realized it with a separate controller. It came out that the controller even was reusable for other cases later on, for which we had no idea when the first app had been implemented.

Former Member
0 Likes

Thanks for the response, but the form I didn't create.  There is nothing else in my page other than what I posted.  Something else is generating this.  If a controller is required how to go about creating that?

Edit

I've just checked and the MIME type for the page is set to application/octet-stream

Thanks

Craig

Ruediger_Plantiko
Active Contributor
0 Likes

Hi Craig,

I just created a page with flow logic with the following sole content:

<%

      response->set_header_field( name = 'Content-Type'        value = 'application/octet-stream' ). 

      response->set_header_field( name = 'Content-Disposition' value = 'attachment; filename=csv_text.csv' ). 

      response->set_header_field( name = 'Connection'          value = 'close' ). 

 

      response->set_header_field( name = 'Expires'       value = '0' ). 

      response->set_header_field( name = 'Pragma'        value = 'no-cache' ). 

      response->set_header_field( name = 'Cache-Control' value = 'max-age=0' ).  

 

      response->set_cdata( 'a;b;c' ). 

%>

It behaves as expected: When I call it, Firefox asks me whether I want to open the csv file with MS Excel, or simply save the file. When I choose "open", excel is started, with the first three cells of the sheet filled with 'a', 'b', 'c'.

Could you try to reduce your code this way and see whether it behaves the same way?

This could give you a hint on what's going wrong.

Rüdiger.

Former Member
0 Likes

Rüdiger

Yes that does what I want my page to do but with me sending it some data.

How to progress from here?

Cheers

Craig

Former Member
0 Likes

Rüdiger,

Ignore me I'm being an idiot, I changed the form from post to get and it worked.

It didn't dawn on me that this might have such an impact.  I simply copied the form from the example given.

Thanks for your time.

Craig

Ruediger_Plantiko
Active Contributor
0 Likes

Hi Craig,

never mind 🙂

If I understand you correctly, the problem was outside of the code you displayed to us, in a HTML form in a previous stage of the app.

Just to finish this discussion: I am curious if you could explain the root cause of the problem in a few words? request->get_form_field( ) works just the same for GET as well as for POST requests. So what was the problem?

Rüdiger

Former Member
0 Likes

Ok here goes.

I had this form in a BW Web template :-

<FORM method="post" action="/sap/bc/bsp/sap/zsavecsv/savefile.bsp">

  <input type="hidden" name="csv_text" id="csv_text"><input type="submit" value="Get CSV File" onclick="getCSVData()">

</FORM>

The getCSVData() javascript function (extension of jQuery) was simply this:-

function getCSVData(){

  var csv_value=$('#TABLE_1').table2CSV({delivery:'value'});

  $("#csv_text").val(csv_value);

}

The BSP page within the layout tab was/is :-

<%

  IF request->get_form_field( 'csv_text' ) IS NOT INITIAL.

  DATA: output TYPE string ,

  app_type TYPE string ,

  l_xstring TYPE xstring.

  DATA: file_content TYPE string. file_content = request->get_form_field( 'csv_text' ).

  REPLACE ALL OCCURRENCES OF ' ' IN file_content WITH ''.

  response->set_header_field( name = 'Content-Type'        value = 'application/octet-stream' ).

  response->set_header_field( name = 'Content-Disposition' value = 'attachment; filename=csv_text.csv' ).

  response->set_header_field( name = 'Connection'          value = 'close' ).

  response->set_header_field( name = 'Expires'       value = '0' ).

  response->set_header_field( name = 'Pragma'        value = 'no-cache' ).

  response->set_header_field( name = 'Cache-Control' value = 'max-age=0' ).

  response->set_cdata( file_content ).

  ENDIF.

%>

The problem: with the form method set to POST, the BSP page had generated by the system (nothing to do with me) a form that submitted to itself with the content of the POSTED field csv_text (plain csv data), then prompted to save the content with a download dialog box.  Leaving you with essentially a blank page.

Simply changing the form method to GET the pre-generated form page doesn't get generated and you simply get what I wanted in the first place, a download dialog.

Hope this makes sense!  Well it doesn't really, since I can't understand why the form page get generated in the first place.

Cheers

Craig

Former Member
0 Likes

OK now I am annoyed, just when you think you have cracked it.

This works in firefox but IE refuses to play ball.

Opens a page with this in the URL :-

/sap/bc/bsp/sap/zsavecsv/savefile.bsp?csv_text=%26nbsp%3B%2C%22No+Applicable+Data+Found.%22%0D%0A%26nbsp%3B%2C%22No+Applicable+Data+Found.%22%0D%0A%26nbsp%3B%2C%22%26nbsp%3B%22%0D%0A%26nbsp%3B%2C%22No+Applicable+Data+Found.%22%0D%0A%26nbsp%3B%2C%22%26nbsp%3B%22%0D%0A%22Channel%22%2C%22%26nbsp%3B%22

But with a lot more on the end which I assume is simply the csv data and refuses to open saying "Internet Explorer cannot display the webpage"

I assume there is an upper limit to a URL string!

Any idea?

Cheers

Craig

Former Member
0 Likes

OK I know why IE doesn't work, according to this http://support.microsoft.com/kb/208427 Maximum URL length is 2,083 characters in Internet Explorer.

So I need to get the POST method working since name/value pairs are transferred in the header and not in the URL.

Help! 😞

Ruediger_Plantiko
Active Contributor
0 Likes

Craig,

I have the suspect that BEx (or something in the calling app) is producing the intermediate self-submitting form, it's not, as you think, the BSP framework.

Proof: I created a second BSP page submit.htm with the following content

<html>

  <head>

    <title>Test submit download</title>

  </head>

  <body>

    <h1>Test Submit Download</h1>

    <form method="post" action="download.htm">

      <input type="text" name="csv_data" value="a;b;c">

      <input type="submit" value="Submit">

    </form>

  </body>

</html>

When calling submit.htm and hitting the button, the download page is called, which I changed like this:

<%  data: lv_csv type string.

    lv_csv = request->get_form_field('csv_data').

    if lv_csv is not initial.

      response->set_header_field( name = 'Content-Type'        value = 'application/octet-stream' ).

      response->set_header_field( name = 'Content-Disposition' value = 'attachment; filename=csv_text.csv' ).

      response->set_header_field( name = 'Connection'          value = 'close' ).

      response->set_header_field( name = 'Content-Lentgh'      value = '0' ).

      response->set_header_field( name = 'Expires'       value = '0' ).

      response->set_header_field( name = 'Pragma'        value = 'no-cache' ).

      response->set_header_field( name = 'Cache-Control' value = 'max-age=0' ).

      response->set_cdata( lv_csv ).

      endif.%>

The page behaves as before, as expected.

This proves that BSP receives the form parameter csv_data without any problems.

Regards,

Rüdiger

Former Member
0 Likes

Rüdiger

Thanks again for coming back to me.  I will try this outside of BW Web Application and replicate as you have directly in BSP.  Unfortunately I think I've killed our DEV box so it'll have to wait until the morning.

I'll let you know how I get on.

Cheers

Craig