使用PHP ,我想创建一个读取大文件的while循环,并在请求时发送当前行号。 使用Ajax ,我想获取当前行数并将其打印到页面上。 使用html按钮,我希望能够单击并激活或终止仅运行ONCE并调用 ajax方法的javascript线程。
我已经给了它一个镜头,但由于某种原因,除非我注释掉echo str_repeat(' ',1024*64);
函数并且当它被注释掉时它没有打印,它显示了整个循环结果:
处理1行.2行处理.3行处理.4行处理.5行处理.6行处理.7行已处理.8行已处理.9行已处理.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>
的test.txt
1
2
3
4
5
6
7
8
9
10
答案 0 :(得分:11)
你对PHP和AJAX如何互动感到困惑。
当您通过AJAX请求PHP页面时,您强制PHP脚本开始执行。虽然您可能正在使用flush()
来清除任何内部PHP缓冲区,但是在关闭连接之前,AJAX调用不会终止(即,不会调用响应处理程序),这在整个文件已经发生时发生读取。
为了实现您的目标,我相信您需要这样的并行流程:
您可以通过$_SESSION
变量或将数据存储到数据库中来完成此进程间通信。无论哪种方式,您都需要并行实现而不是当前的顺序实现,否则您将立即继续获得整个状态。
答案 1 :(得分:9)
使用:
应该在一个php线程中完成你需要的所有东西
修改强>
看看nickb的答案,如果你正在寻找一种方法,只需按照算法进行:
process.php
(这将完成所有工作和打印状态报告),你必须查看jQuery ajax是否支持连续加载在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页面:
<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>
点击开始行后:
Line 1
Line 2
出现在div #foo
中。当我点击Stop
时,它们停止显示,但脚本在后台完成,并将所有100个数字写入文件。
如果你再次点击Start
脚本开始从begging(重写文件)执行,那么并行请求就会执行。
有关http流的更多信息,请参阅this link
答案 2 :(得分:3)
更简单的解决方案应该是使用原生(vanila js)XHR对象。
那里有非常复杂的解决方案,关于long polling
PHP:
<?php
header('Content-Type: text/html; charset=UTF-8');
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++){
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "Done.";
ob_end_flush();
JS:
var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/some_service.php', true);
xhr.send(null);
xhr.onreadystatechange = function() {
if (xhr.status == 200) {
if (xhr.readyState == XMLHttpRequest.LOADING){
console.log('response',xhr.response);
// this can be also binary or your own content type
// (Blob and other stuff)
}
if (xhr.readyState == XMLHttpRequest.DONE){
console.log('response',xhr.response);
}
}
}
答案 3 :(得分:0)
诀窍是创建一个文件(通过Ajax更新)并使用setInterval
获取其值,然后更新进度条。