开发者

can sinatra re-stream output from php script through ajax?

I have a php script running on server A that takes like 15mins to finish. I run the script through the web browser and it sends out output to the browser in blocks (as some php commands finished). See below for example of the blocks. The script creates DB2 database and it requires few steps in total.

Now I run the same script from sinatra on server B through AJAX. It works fine but I get the whole lot of output (all blocks as I call it) once the php script finishes.

Is there any way the sinatra/ajax can be set up the way so it works the same way as if the script is started directly from the browser (not from sinatra)? So I can see results of every block once it finishes not when the whole ajax call finishes.

HAML file (extract)

:javascript
  function loadXMLDoc2(mode)
  {
    if (window.XMLHttpRequest)
      {// code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else
      {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function()
      {
      document.getElementById("db2").innerHTML="<BLINK> processing</BLINK> "+mode+" procedure";
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
        document.getElementById("db2").innerHTML=xmlhttp.responseText;
        }
      }
    xmlhttp.open("GET","/ajaxdb2?mode="+mode,true);
    xmlhttp.send();
     }

    %td 
      %button{:type => "button", :onclick => "loadXMLDoc2('create')"}
        create DB2
      %br

ruby code (extract)

get '/ajaxdb2?' do

  execute_db2_script(params['mode'].downcase)
end 

def execute_db2_script(mode)

  if not (mode == 'clear')

    db2_database = 'RATIONAL'
    url = "http://db2express/imacs/radek/db2.rft/rationa开发者_开发百科lTest.php?mode=#{mode}&database=#{db2_database}"
uri = URI.parse(url)
start = Time.new

response = Net::HTTP.start(uri.host, uri.port) do |http|
  http.open_timeout =  5
  http.read_timeout = 1500
  http.request_get(uri.request_uri)
end

stop = Time.new

return "#{response.body} <BR>processed in #{stop - start} seconds"
 else
  return "DB2 results"
 end
end

PHP code sample (2blocks)

flush_buffers();

$output = array();
$shellOutput = exec("echo 'password' | sudo -su db2inst1 -S '/opt/ibm/db2/V9.7/bin/db2 deactivate database $databaseName'", $output);

echo "<pre>Output = " . print_r($output,1) . "</pre>";
if( strpos($output[0],'DB20000I') === false && strpos($output[0],'SQL1496W') === false && strpos($output[0],'SQL1013N') === false && strpos($output[0],'SQL30061N') === false ){
    echo("Could not deactivate database.");
}
flush_buffers();


$output = array();
$shellOutput = exec("sudo -su db2inst1 -S '/opt/ibm/db2/V9.7/bin/db2 drop database $databaseName'", $output);
echo "<pre>Output = " . print_r($output,1) . "</pre>";
if( strpos($output[0],'DB20000I  The DROP DATABASE command completed successfully') === false && strpos($output[0],'SQL1013N') === false && strpos($output[0],'SQL30061N') === false ){
    echo("Dropping of the database was not successful.");
}


I'm at home now and my code is at work but you do it by piping the output to a log file (or using popen) then showing the log file lines as they grow/pipe using a session line holder...

I used a jquery ui progress bar (optional) tied to a ajax call (in jquery that faces the client) with a go button that fired off the exec then waited until a session variable had the string "complete in it and I had a single PHP $.ajax get page outputing the contents of the session variable every time it was called.

the one off fire off

<?
session_start();
$_SESSION['latestline']="starting";
exec("somelongjobmultiline >c:\temp\log.log");
?>

the session variable updater

<?
//session getter for the $.ajax call will continue til its saying "complete"
session_start();
//code to go to the log.log or read the popen output
echo $_SESSION['latestline'];
?>

I'll post the actual code I use tomorrow


ok here it is in PHP:

for the demo: make a C:\Temp\sleep.bat and have the lines in it this will take 5 seconds to poll results - make sure there is no file called C:\Temp\info.log

@echo. > C:\Temp\info.log
@echo working start > C:\Temp\info.log
@ping 123.45.67.89 -n 1 -w 1000 > nul
@echo working 1 second > C:\Temp\info.log
@ping 123.45.67.89 -n 1 -w 1000 > nul
@echo working 2 seconds > C:\Temp\info.log
@ping 123.45.67.89 -n 1 -w 1000 > nul
@echo working 3 seconds > C:\Temp\info.log
@ping 123.45.67.89 -n 1 -w 1000 > nul
@echo working 4 seconds > C:\Temp\info.log
@ping 123.45.67.89 -n 1 -w 1000 > nul
@echo done (after 5) > C:\Temp\info.log

then an index.php, launchprocess.php, getprocessstatus.php, style.css wherever you like but in the same folder

index.php

<?php
    //index.php
    session_start();
    $_SESSION['out']="";

    echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n";
    echo "<html>\n";
    echo "<head>\n";
    echo "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n";
    echo "    <title>Demo</title>   \n";
    echo "\n";
    echo "    <link rel=\"stylesheet\" href=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/themes/base/jquery-ui.css\" media=\"screen\" />\n";
    echo "    <script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js\"></script>\n";
    echo "    <script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js\"></script>\n";
    echo "  \n";
    echo "  <link rel=\"stylesheet\" href=\"style.css\" media=\"screen\" />\n";

    echo "<script>\n";
    echo "  $(document).ready(function(){\n";
    echo "      \n";
    echo "      $('#go').click(function(){\n";
    echo "          $.ajax({\n";
    echo "              cache: false,\n";
    echo "              type: 'post',\n";
    echo "              url: 'launchprocess.php',\n";
    echo "              beforeSend: start_display()\n";
    echo "          });\n";
    echo "      });\n";
    echo "      \n";
    echo "  });\n";
    echo "\n";
    echo "  var interval='';\n";
    echo "  var counter=1;\n";
    echo "      \n";
    echo "  function start_display() {\n";
    echo "      $(\".button\").val(\"...hold on a minute\"); \n";
    echo "      $(\".button\").attr(\"disabled\", true); \n";
    echo "      if (interval==\"\") {\n";
    echo "          interval=window.setInterval(\"display()\",200);\n";
    echo "      } else {\n";
    echo "          stop_display();\n";
    echo "      }\n";
    echo "  }\n";
    echo "\n";
    echo "  function stop_display() {\n";
    echo "      $(\".button\").val(\"Click to go!\"); \n";
    echo "      $(\".button\").attr(\"disabled\", false); \n";
    echo "      if (interval!=\"\") {\n";
    echo "          window.clearInterval(interval);\n";
    echo "          interval=\"\";\n";
    echo "      }\n";
    echo "  }\n";
    echo "\n";
    echo "  function display() {\n";
    echo "      counter ++; \n";
    echo "      if (counter=='100') {\n";
    echo "          stop_display();\n";
    echo "          $('#text').html('Timeout');\n";
    echo "      }\n";
    echo "      $.ajax({\n";
    echo "          cache: false,\n";
    echo "          type: 'get',\n";
    echo "          url: 'getprocessstatus.php',\n";
    echo "          success: function(response) {\n";
    echo "              $('#text').html(response);\n";
    echo "              if (response=='100' || response =='done' || response =='complete') {\n";
    echo "                  stop_display();\n";
    echo "                  $('#text').html('Done!');\n";
    echo "              }\n";
    echo "          }\n";
    echo "      });\n";
    echo "  }\n";
    echo "  \n";
    echo "</script>\n";

    echo "\n";
    echo "</head>\n";
    echo "<body>\n";
    echo "\n";
    echo "<div id=\"step\">\n";
    echo "      <h1>Run Demo</h1>\n";
    echo "      <input type=\"button\" value=\"Click to go!\" class=\"button green\" id=\"go\">\n";
    echo "      <div id=\"text\"></div>\n";
    echo "</div>\n";
    echo "\n";
    echo "</body>\n";
    echo "</html>\n";
?>

launchprocess.php

<?php
    // file: launchprocess.php
    session_start();

    function command($cmd){
        session_start();
        $_SESSION['out'] = "";
        session_commit();

        session_write_close();
        exec($cmd,$out);
        session_commit();

        foreach($out as $line){
            if ($line) $store .= $line . "<br>";
        }       
    }

    session_start();    
    $_SESSION['out'] = "setting up";
    session_commit();

    command("C:\\Temp\\Sleep.bat"); 

    session_start();    
    $_SESSION['out'] = "done";
    session_commit();
?>

getprocessstatus.php

<?php
    // file: getprocessstatus.php
    session_start();

    if ($_SESSION['out']) echo $_SESSION['out'];
    else {
        $filename = "C:\\Temp\\info.log";
        if (is_file($filename)){
            $handle = fopen($filename, "r");
            echo fread($handle, filesize($filename));
            fclose($handle);
        }
        else{
            echo "no file";
        }
    }
?>

style.css

body {
        margin: 100px 0 0 200px;
}

h1 {
    font-family: calibri, arial;
    font-weight: bold;
}

div {
    font-family: calibri, arial;
    font-weight: bold;
}

#response {
    width: 500px;
    height: 20px;
    backgorund: #fff;
    background: -webkit-gradient(linear, 0 0, 0 100%, from(#f1f1f1), to(#fff));
    background: -moz-linear-gradient(top, #f1f1f1, #fff);
    border: 1px solid #ccc;
    border-radius: 2px;
    -moz-border-radius: 2px;
    margin: 0 0 20px 0;
    display: none;
}
#response div {
    height: 100%;
    width: 0;
    border: none;
    background: #84D700;
    -moz-box-shadow: 2px 0 5px #ccc;
    -webkit-box-shadow: 2px 0 5px #ccc;
    box-shadow: 2px 0 5px #ccc;
}
#loader {
    vertical-align: middle;
    margin: 0 10px 0 0;
    display: none;
}

.button {
    font-family: calibri, arial;
    font-weight: bold;
    color: white;
    font-size: 18px;
    padding:7px;
    -moz-border-radius: 5px;
    border-radius: 5px;
    width: 220px;
}

.green {
    background-color: #9BBB59;  
    border: solid 3px #71893F;  
}

.purple {
    background-color: #8064A2;  
    border: solid 3px #5C4776;  
}

.blue {
    background-color: #4F81BD;  
    border: solid 3px #385D8A;  
}

.cyan {
    background-color: #4BACC6;  
    border: solid 3px #357D91;  
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜