2012-02-05 175 views
17

使用PHP,我想製作一個while循環,讀取大文件並在請求時發送當前行號。 使用Ajax,我想獲得當前行數並將其打印到頁面上。 使用html按鈕,我希望能夠點擊並激活或終止一個只運行一次的javascript線程,並調用ajax方法PHP - 使用Ajax刷新while循環數據

我給它一個鏡頭,但由於某些原因,沒有打印除非我註釋掉echo str_repeat(' ',1024*64);功能,當它註釋掉,它顯示了整個循環的結果:

1行(S)processed.2行(s)已處理.3行已處理.4行已處理.5行已處理.6行已處理.7行已處理.8行已處理.9行(行) s)已處理10行。

在一個行,而不是表示與單獨行他們喜歡:

1 row(s) processed. 
2 row(s) processed. 
3 row(s) processed. 
4 row(s) processed. 
5 row(s) processed. 
6 row(s) processed. 
7 row(s) processed. 
8 row(s) processed. 
9 row(s) processed. 
10 row(s) processed. 

而且我不知道如何結束的JavaScript線程。所以總共有2個問題:

1. It's returning the entire While loop object at once instead of each time it loops. 
2. I'm not sure how to terminate the JQuery thread. 

任何想法?以下是我的代碼到目前爲止。

msgserv.php

<?php 

//Initiate Line Count 
$lineCount = 0; 

// Set current filename 
$file = "test.txt"; 

// Open the file for reading 
$handle = fopen($file, "r"); 

//Change Execution Time to 8 Hours 
ini_set('max_execution_time', 28800); 

// Loop through the file until you reach the last line 
while (!feof($handle)) { 

    // Read a line 
    $line = fgets($handle); 

    // Increment the counter 
    $lineCount++; 

    // Javascript for updating the progress bar and information 
    echo $lineCount . " row(s) processed."; 

    // This is for the buffer achieve the minimum size in order to flush data 
    //echo str_repeat(' ',1024*64); 

    // Send output to browser immediately 
    flush(); 

    // Sleep one second so we can see the delay 
    //usleep(100); 
} 

// Release the file for access 
fclose($handle); 

?> 

asd.html

<html> 
    <head> 
     <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript" charset="utf-8"></script> 

     <style type="text/css" media="screen"> 
      .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid} 
      .new{ background-color:#3B9957;} 
      .error{ background-color:#992E36;} 
     </style> 

    </head> 
    <body> 

    <center> 
     <fieldset> 
      <legend>Count lines in a file</legend> 
      <input type="button" value="Start Counting" id="startCounting" /> 
      <input type="button" value="Stop Counting!" onclick="clearInterval(not-Sure-How-To-Reference-Jquery-Thread);" /> 
     </fieldset> 
    </center> 

    <div id="messages"> 
     <div class="msg old"></div> 
    </div> 

    <script type="text/javascript" charset="utf-8"> 
     function addmsg(type, msg){ 
      /* Simple helper to add a div. 
     type is the name of a CSS class (old/new/error). 
     msg is the contents of the div */ 
      $("#messages").append(
      "<div class='msg "+ type +"'>"+ msg +"</div>" 
     ); 
     } 

     function waitForMsg(){ 
      /* This requests the url "msgsrv.php" 
     When it complete (or errors)*/ 
      $.ajax({ 
       type: "GET", 
       url: "msgsrv.php", 
       async: true, /* If set to non-async, browser shows page as "Loading.."*/ 
       cache: false, 
       timeout:2880000, /* Timeout in ms set to 8 hours */ 

       success: function(data){ /* called when request to barge.php completes */ 
        addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/ 
        setTimeout(
        'waitForMsg()', /* Request next message */ 
        1000 /* ..after 1 seconds */ 
       ); 
       }, 
       error: function(XMLHttpRequest, textStatus, errorThrown){ 
        addmsg("error", textStatus + " (" + errorThrown + ")"); 
        setTimeout(
        'waitForMsg()', /* Try again after.. */ 
        "15000"); /* milliseconds (15seconds) */ 
       }, 
      }); 
     }; 

     $('#startCounting').click(function() { 
      waitForMsg(); 
     }); 
    </script> 

</body> 
</html> 

測試。TXT

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 

回答

8

使用:

應該盡一切可能在一個PHP線程需要

編輯

看看nickb的回答,如果你正在尋找一種方式如何做到這一點簡單地將它下面的算法:

  1. 的javascript通過ajax打開process.php(這將做所有的工作和打印狀態報告),你要回去看看jQuery的AJAX是否支持連續加載
  2. 如果用戶決定停止刷新你會提供的鏈接殺裝載的節目

process.php

ignore_user_abort(); // Script will finish in background 
while(...){ 
    echo "Page: $i\n"; 
    ob_flush(); 
} 

編輯2請求例如(的不同和難看,但簡單的比特)。 test_process.php

// This script will write numbers from 1 to 100 into file (whatever happens) 
// And sends continuously info to user 
$fp = fopen('/tmp/output.txt', 'w') or die('Failed to open'); 
set_time_limit(120); 
ignore_user_abort(true); 

for($i = 0; $i < 100; $i++){ 
    echo "<script type=\"text/javascript\">parent.document.getElementById('foo').innerHTML += 'Line $i<br />';</script>"; 
    echo str_repeat(' ', 2048); 
    flush(); 
    ob_flush(); 
    sleep(1); 
    fwrite($fp, "$i\n"); 
} 

fclose($fp); 

及主要的html頁面:

Line 1 
Line 2 

在div #foo出現了:

<iframe id="loadarea"></iframe><br /> 
<script> 
function helper() { 
    document.getElementById('loadarea').src = 'test_process.php'; 
} 
function kill() { 
    document.getElementById('loadarea').src = ''; 
} 
</script> 

<input type="button" onclick="helper()" value="Start"> 
<input type="button" onclick="kill()" value="Stop"> 
<div id="foo"></div> 

打開始的線爲後。當我點擊Stop時,它們停止出現,但腳本在後臺完成,並將全部100個數字寫入文件。

如果再次點擊Start,腳本開始從請求(重寫文件)開始執行,所以並行請求也會執行。

對於HTTP流的詳細信息請參見this link

+0

嗨 - 非常感謝。我嘗試了你的建議,但他們都沒有爲我工作。你能否保存我提供的3個文件,並告訴我他們是否適合你?如果是這樣,你能分享你發現的東西嗎? – ThreaT 2012-02-05 20:07:29

+0

@ user1191027閱讀編輯 – Vyktor 2012-02-05 20:15:38

+0

嘿,再次感謝 - 我嘗試了你的新建議,但仍然沒有運氣......他們是否爲你工作? – ThreaT 2012-02-05 20:29:52

11

您對如何PHP和AJAX交互感到困惑。

當您通過AJAX請求PHP頁面時,您強制PHP腳本開始執行。雖然您可能正在使用flush()來清除任何內部PHP緩衝區,但在連接關閉之前,AJAX調用不會終止(即不會調用響應處理程序),這會在整個文件被讀取時發生。

來完成你在找什麼,我相信你會需要這樣的並行處理流程:

  1. 第一個AJAX後發送到開始讀取文件的請求。該腳本生成一些unqiue ID,將其發送回瀏覽器,生成一個實際執行文件讀取的線程,然後終止。
  2. 所有後續的AJAX請求轉到另一個PHP腳本,用於檢查文件讀取的狀態。這個新的PHP腳本根據#1中生成的唯一ID發送文件讀取的當前狀態,然後退出。

您可以通過$_SESSION變量或將數據存儲到數據庫中來完成此進程間通信。無論哪種方式,您都需要一個並行實現,而不是當前的順序實現,否則您將繼續一次獲得整個狀態。

+0

嗨 - 非常感謝。我嘗試了你的建議,但他們都沒有爲我工作。你能否保存我提供的3個文件,並告訴我他們是否適合你?如果是這樣,你能分享你發現的東西嗎? – ThreaT 2012-02-05 20:14:04

0

訣竅是創建一個文件(通過Ajax更新)並使用setInterval來獲取其值,然後更新進度條。

+0

提供的網址不再有效 – mattspain 2015-08-15 18:12:06

+0

一個爲什麼你應該在答案內發佈內容而不是簡單鏈接的例子。 – 2015-08-19 20:43:10

+0

完全理解。從現在開始我會這樣做。 – 2015-08-20 10:14:06