Skip to Content

As we all know SAP has some great tools for uploading files into the system, but what if you want to create a completely custom web page that supported cross browser uploads and json….hmmm not so easy!

While searching the web one day I came across a toolkit called PLUpload http://www.plupload.com/ but this was pure javascript. The features looked perfect for what I was needing to do.

Screenshot-2012-09-19_08.58.47.png

How could I get this into SAP and be usable? Well here is how I did it.

1. First download the open source project http://www.plupload.com/download.php

2. Go to SE80 and create a new BSP Application.

3. Create a new contoller, in my case I called in index.do. You will have to create an new class that is associated with the controller.

4. Inside the new class you need to redefine the DO_REQUEST method.

5. Within this method you need to tell it which view to execute and open (we’ll create the new view later).

method DO_REQUEST.

   data view type ref to if_bsp_page.

   data pagePassed type c.

   pagePassed = .

   data: ls_field type ihttpnvp,

        lt_field type tihttpnvp.

  request->get_form_fields( CHANGING fields = lt_field ).

  loop at lt_field into ls_field.

    if ls_fieldname = ‘page’.

      if ls_fieldvalue = ‘home’.

         me->view_name = ‘index.htm’.

         view = me->create_view( view_name = me->view_name ).

         pagePassed = ‘X’.

         if view is bound.

           me->call_view( view ).

         endif.

      ELSEIF ls_fieldvalue = ‘valid’.

         me->view_name = ‘valid.htm’.

         view = me->create_view( view_name = me->view_name ).

         pagePassed = ‘X’.

         if view is bound.

           me->call_view( view ).

         endif.

      endif.

    endif.

  ENDLOOP.

if pagePassed = .

   me->view_name = ‘index.htm’.

   view = me->create_view( view_name = me->view_name ).

   if view is bound.

     me->call_view( view ).

   endif.

endif.

endmethod.

6. Now we need to create the views. Under the views folder, right-click and create. This is where we will place the html code to add the PLUpload.


<%@page language=”abap”%>

<!– Load Queue widget CSS and jQuery –>

<link rel=“stylesheet” href=“style.css” media=“screen”>

<link rel=“stylesheet” href=“plupload/jquery.plupload.queue/css/jquery.plupload.queue.css”>

<script type=“text/javascript” src=“jquery.min.js”></script>

<!– Third party script for BrowserPlus runtime (Google Gears included in Gears runtime now) –>

<script type=“text/javascript” src=“browserplus-min.js”></script>

<!– Load plupload and all it’s runtimes and finally the jQuery queue widget –>

<script type=“text/javascript” src=“plupload/plupload.full.js”></script>

<script src=“jquery.uniform.js” type=“text/javascript” charset=“utf-8”></script>

<link rel=“stylesheet” href=“uniform.default.css” type=“text/css” media=“screen”>

<%= runtime->session_manager->header_script( ) %>

   <script type=“text/javascript”>

     function newPopup() {

       var url = getCookie(‘file’);

       var newURL = ‘log.htm?log=’ + url;

       popupWindow = window.open(

         newURL,‘Log’,‘height=700,width=800,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes’)

     }

     function setCookie(c_name,value,exdays)

     {

       var exdate=new Date();

       exdate.setDate(exdate.getDate() + exdays);

       var c_value=escape(value) + ((exdays==null) ? “” : “; expires=”+exdate.toUTCString());

       document.cookie=c_name + “=” + c_value;

     }

     function getCookie(c_name)

     {

       var i,x,y,ARRcookies=document.cookie.split(“;”);

       for (i=0;i<ARRcookies.length;i++)

       {

         x=ARRcookies[i].substr(0,ARRcookies[i].indexOf(“=”));

         y=ARRcookies[i].substr(ARRcookies[i].indexOf(“=”)+1);

         x=x.replace(/^\s+|\s+$/g,“”);

         if (x==c_name)

           {

           return unescape(y);

           }

       }

     }

     function checkCookie()

     {

       var username=getCookie(“username”);

         if (username!=null && username!=“”)

         {

         alert(“Welcome again ” + username);

         }

       else

         {

         username=prompt(“Please enter your name:”,“”);

         if (username!=null && username!=“”)

           {

           setCookie(“username”,username,365);

           }

         }

     }

   </script>

<script type=“text/javascript” src=“plupload/jquery.plupload.queue/jquery.plupload.queue.js”></script>

<style type=“text/css” media=“screen”>

       body {

         font-family: “Helvetica Neue”, Helvetica, Arial, sans-serif;

         color: #666;

         padding: 40px;

       }

       h1 {

         margin-top: 0;

       }

       ul {

         list-style: none;

         padding: 0;

         margin: 0;

       }

       li {

         margin-bottom: 20px;

         clear: both;

       }

       label {

         font-size: 10px;

         font-weight: bold;

         text-transform: uppercase;

         display: block;

         margin-bottom: 3px;

         clear: both;

       }

</style>

<script type=“text/javascript”>

// Convert divs to queue widgets when the DOM is ready

$(function() {

      $(“input, textarea, select, button”).uniform();

      function log() {

       var str = “”;

       plupload.each(arguments, function(arg) {

         var row = “”;

         if (typeof(arg) != “string”) {

           plupload.each(arg, function(value, key) {

             // Convert items in File objects to human readable form

             if (arg instanceof plupload.File) {

               // Convert status to human readable

               switch (value) {

                 case plupload.QUEUED:

                   value = ‘QUEUED’;

                   break;

                 case plupload.UPLOADING:

                   value = ‘UPLOADING’;

                   break;

                 case plupload.FAILED:

                   value = ‘FAILED’;

                   break;

                 case plupload.DONE:

                   value = ‘DONE’;

                   break;

               }

             }

             if (typeof(value) != “function”) {

               row += (row ? ‘, ‘ : ) + key + ‘=’ + value;

             }

           });

           str += row + ” “;

         } else {

           str += arg + ” “;

         }

       });

       $(‘#log’).append(str + “\n”);

      }

   $(“#uploader”).pluploadQueue({

     // General settings

     runtimes : ‘gears,flash,silverlight,browserplus,html5’,

     url : ‘upload.htm’,

     max_file_size : ’10mb’,

     unique_names : true,

     multiple_queues : true,

     dragdrop : true,

     // Resize images on clientside if we can

     resize : {width : 320, height : 240, quality : 90},

     // Specify what files to browse for

     filters : [

       {title : “EVMS Files”, extensions : “txt,csv”}

     ],

     // Flash settings

     flash_swf_url : ‘plupload/plupload.flash.swf’,

     // Silverlight settings

     silverlight_xap_url : ‘plupload/plupload.silverlight.xap’,

     // PreInit events, bound before any internal events

     preinit : {

       Init: function(up, info) {

         log(‘[Init]’, ‘Info:’, info, ‘Features:’, up.features);

       },

       UploadFile: function(up, file) {

         log(‘[UploadFile]’, file);

         var strparam = “”;

         var strparam2 = “”;

         if($(‘#sapload:checked’).val()?true:false){

           strparam = “X”;

         }

         if($(‘#validate:checked’).val()?true:false){

           strparam2 = “X”;

         }

         if(strparam == “X” && strparam2 == “X”){

           up.settings.multipart_params = { ‘sap’:‘X’,‘valid’:‘X’ };

         }

         else

         {

           if(strparam == “X” )

           {

             up.settings.multipart_params = { ‘sap’:‘X’ };

           }

           if(strparam2 == “X”)

           {

             up.settings.multipart_params = { ‘valid’:‘X’ };

           }

         }

         // You can override settings before the file is uploaded

         // up.settings.url = ‘upload.php?id=’ + file.id;

         // up.settings.multipart_params = {param1 : ‘value1’, param2 : ‘value2’};

       }

     },

     // Post init events, bound after the internal events

     init : {

       Refresh: function(up) {

         // Called when upload shim is moved

         log(‘[Refresh]’);

       },

       StateChanged: function(up) {

         // Called when the state of the queue is changed

         log(‘[StateChanged]’, up.state == plupload.STARTED ? “STARTED” : “STOPPED”);

       },

       QueueChanged: function(up) {

         // Called when the files in queue are changed by adding/removing files

         log(‘[QueueChanged]’);

       },

       UploadProgress: function(up, file) {

         // Called while a file is being uploaded

         log(‘[UploadProgress]’, ‘File:’, file, “Total:”, up.total);

       },

       FilesAdded: function(up, files) {

         // Callced when files are added to queue

         log(‘[FilesAdded]’);

         plupload.each(files, function(file) {

           log(‘  File:’, file);

         });

       },

       FilesRemoved: function(up, files) {

         // Called when files where removed from queue

         log(‘[FilesRemoved]’);

         plupload.each(files, function(file) {

           log(‘  File:’, file);

         });

       },

       FileUploaded: function(up, file, info) {

         // Called when a file has finished uploading

         log(‘[FileUploaded] File:’, file, “Info:”, info);

         info = jQuery.parseJSON( info.response );

            if(info.error != null || info.error != undefined)

            {

               if (info.error.code){

                 log(‘[error] ‘, info.error.message);

                 file.status = plupload.FAILED;

                 setCookie(‘file’,file.name,1);

                 $(‘#errorlist’).append(‘<div class=”error”><a href=”javascript:newPopup();”>Error loading file ‘ + file.name + ‘ – Please check log for more detail.</a></div>’);

                 up.trigger(‘UploadProgress’, file);

<%–                 up.trigger(‘Error’, {

                    code : info.error.code,

                    message : info.error.message,

                    details : info.details,

                    file : file

                  });–%>

               }

            }

            else

            {

              $(‘#errorlist’).append(‘<div class=”success”>’ + file.name + ‘ was successful</div>’);

            }

       },

       ChunkUploaded: function(up, file, info) {

         // Called when a file chunk has finished uploading

         log(‘[ChunkUploaded] File:’, file, “Info:”, info);

       },

       Error: function(up, args) {

         // Called when a error has occured

         log(‘[error] ‘, args);

         setCookie(‘file’,args.file.name,1);

         $(‘#errorlist’).append(‘<div class=”error”><a href=”javascript:newPopup();”>Error loading file ‘ + args.file.name + ‘ – Please check log for more detail.</a></div>’);

         up.start();

       }

     }

   });

   // Client side form validation

   $(‘form’).submit(function(e) {

         var uploader = $(‘#uploader’).pluploadQueue();

         // Files in queue upload them first

         if (uploader.files.length > 0) {

             // When all files are uploaded submit form

             uploader.bind(‘StateChanged’, function() {

                 if (uploader.files.length === (uploader.total.uploaded + uploader.total.failed)) {

                     $(‘form’)[0].submit();

                 }

             });

             uploader.start();

         } else {

             alert(‘You must queue at least one file.’);

         }

         return false;

     });

});

</script>

<form ..>

   <div id=“uploader”>

     <p>You browser does not have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>

   </div>

     <label><input type=“checkbox” name=“validate” id=“validate” /> Validate File</label>

     <label><input type=“checkbox” name=“sapload” id=“sapload” /> Load into SAP</label>

   <!– Error List –>

   <!–div id=”log” class=”cb”></div–>

   <div id=“errorlist” class=“cb”></div>

</form>

7. One of the most important pieces in the code above is line

     $(“#uploader”).pluploadQueue({

          // General settings

          runtimes : ‘gears,flash,silverlight,browserplus,html5’,

          url : ‘upload.htm’,

          max_file_size : ’10mb’,

          unique_names : true,

          multiple_queues : true,

          dragdrop : true,

The url is the url that the data will be sent to and this is also were we need to do some json string stuff.

8. Now under the Pages with Flow Logic, right-click and create a page called upload.htm

9. Under the Event Handler tab, select OnRequest. This is where the magic occurs.

data: ls_field type ihttpnvp,

        lt_field type tihttpnvp.

data: runValid type c,

       runSAP type c.


request->get_form_fields( CHANGING fields = lt_field ).

loop at lt_field into ls_field.

   if ls_fieldname = ‘valid’.

     runValid = ‘X’.

   ELSEIF ls_fieldname = ‘sap’.

     runSAP = ‘X’.

   endif.

ENDLOOP.

DATA: content    TYPE STRING,

       Xcontent   TYPE XSTRING,

       entity     TYPE REF TO if_http_entity,

       idx        TYPE I VALUE 1,

       content_type type string.

WHILE idx <= request->num_multiparts( ).

   entity = request->get_multipart( idx ).

   idx = idx + 1.

   IF entity->get_header_field( ‘~content_filename’ ) IS INITIAL.

     CONTINUE.

   ENDIF.

   data filename type string.

   filename = entity->get_header_field( ‘~content_filename’ ).

   content_type = entity->get_header_field( ‘Content-Type’ ).

   Xcontent = entity->get_data( ).

   IF XSTRLEN( Xcontent ) IS INITIAL.

     CONTINUE.

   ENDIF.

   DATA: conv   TYPE REF TO CL_ABAP_CONV_IN_CE.

   conv = CL_ABAP_CONV_IN_CE=>CREATE( input = Xcontent ).

   conv->READ( importing data = content ).

   EXIT.

ENDWHILE.

if content is not INITIAL.

     “This is were the contents of the file are.

    

  “Here is do whatever we need to the data. Do a check in this case subrc. If successful send success else send error.

  if NOT sysubrc = 0.

     CONCATENATE ‘{“jsonrpc” : “2.0”, “result” : null, “id” : “id”}’ into xml_string.

   else.

     xml_string = ‘{“jsonrpc” : “2.0”, “error” : { “code”:”100″,”message”:”File Failed to load. See error log for more detail.” }, “id”:”id”}’.

   endif.

   “xml_string = ‘[{“name”:”picture1.jpg”,”size”:902604,”url”:”\/\/example.org\/files\/picture1.jpg”,”thumbnail_url”:”\/\/example.org\/thumbnails\/picture1.jpg”,”delete_url”:”\/\/example.org\/upload-     handler?file=picture1.jpg”,”delete_type”:”DELETE”}]’.

    CALL METHOD _M_RESPONSE->IF_HTTP_ENTITY~SET_CDATA

       EXPORTING

         DATA = XML_STRING.

endif.

10. Now we need to load all the javascripts that we downloaded from the PLUpload site.

11. Create a folder called plupload and do a mime import for each file (this is the painful part).

12. Go download jquery and add this to the mime as well http://www.jquery.com/

13. Once everything is added and you want to test the new code. Right-click on the index.do file and select test.

14. You should see something like this….

Screenshot-2012-09-19_09.20.44.png

To report this post you need to login first.

1 Comment

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

Leave a Reply