2012-02-05 173 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