立即显示冗长的PHP脚本的中间结果

时间:2015-05-16 04:15:38

标签: php

我的data目录中有8000个html文件。我通过遍历目标目录解析所有html文件并调用解析函数。文件名将在我的程序中解析。

<?php
base_dir="c:\data";
function parse($fname){
//to parse data from the file,omitted codes
    echo $fname;
    }   

foreach(new RecursiveDirectoryIterator(base_dir) as $item){
    parse($item);
    }
?> 

我发现文件名将显示在网页上,直到我的整个php文件被执行,文件名将在10分钟后显示,当一个文件被削减时,文件名不会逐一显示。 如何在网页上一个一个地显示结果,而不是等到整个php文件完成? 对我来说,知道我的代码是否存在问题是非常重要的,如果长时间过去,网页上显示的任何内容都不会让我感到紧张。

3 个答案:

答案 0 :(得分:1)

如果只需跟踪程序执行情况,可以使用error_log($ fname)命令代替&#39; echo&#39;。比AJAX更省力,你可以跟踪执行情况&#39; live&#39;通过粘贴在Ubuntu终端:

tail -F /var/log/apache2/error.log

(在其他* nix路径上可能不同)。

答案 1 :(得分:0)

您的意思是在没有刷新网页的情况下显示结果吗? 如果是这样,你可以使用ajax发送请求。

答案 2 :(得分:0)

1。 PLAIN

简单的方法是禁用任何输出缓冲,并使用flush进行测量。另外,禁用压缩。

<?php
    while (ob_get_level()) {
        ob_end_clean(); // or ob_end_flush() if you want to display previous output from this script.
    }

    ...
    print "Whatever\n";
    flush();

以上版本允许对您当前代码的最小修改。它几乎没有任何保证,因为解析过程和浏览器之间的实际工作流程可能包含几乎没有控制权的实体(代理等);如果你执行外部程序,那些可能是完全缓冲而不是行缓冲;等等。

2。 AJAX

如果可能的话,更复杂(但令人满意)的方法是将其分成两个块。这也带来了需要解决的安全风险。

在主PHP文件中输出一个Javascript变量(在Javascript块中)。

print "var filesToProcess = [\n";

print implode(",", array_map(
    function($rawFileName) {
        return '"' . /*javascriptQuote*/($rawFileName) . '"';
    },
    $filesToProcess
));
print "];\n";

这将使客户端Javascript成为包含所有文件的数组。

您现在可以在AJAX中进行处理:

 function processOneFile() {
     if (!window.filesToProcess.length) {
         return;
     }
     // jQuery
     $.post('/path/to/processor.php',
         { file: window.filesToProcess.pop() },
         function(result) {
            // ... see below
         }
     ).always(function(){
         window.setTimeout('processOneFile', 100);
     });
 } 

window.setTimeout('processOneFile', 100);

这将调用带有一个文件的PHP文件来处理另一个文件。必须以JSON:

返回结果
Header("Content-Type: application/json;charset=UTF-8");
die(json_encode(array( "status" => "OK", "file" => $file, "problem" => null )));

安全风险:客户端正在发送文件名任何文件名,脚本正在执行该操作。通常您不知道客户端是谁,或者它可能是,因此您需要验证文件名(例如确定其基本名称确实存在于目标中)你首先发送的目录):

if (!file_exists($yourDir . DIRECTORY_SEPARATOR . basename($file)) {
    Header("Content-Type: application/json;charset=UTF-8");
    die(json_encode(array(
        "status" => "FAILED",
        "file" => $file,
        "problem" => "file could not be found",
        /* "real-problem" => "Sorry, friend, it didn't work." */
    )));
}

数组将返回上面的Javascript函数:

function(result) {
    var msg;
    if (result.status == "OK") {
        msg = result.file + " OK";
    } else {
        msg = result.file + ": " + result.problem
    }
    $('#logDiv').append($('<p>').text(msg));
}

以上将转换HTML实体

<div id="logDiv"></div>

in,比如说,

<div id="logDiv">
    <p>file1.pdf OK</p>
    <p>file2.pdf: missing UUID entry</p>
    ...
</div>

由于你知道初始filesToProcess.length,你也可以显示一个进度条(甚至有jQuery插件可以像$('#bar').progress(n*100/initialLength)那样简单。)

或者你可以通过发送两个日志行来运行冗长的进程,一个就在$ .post

之前
$('#logDiv').append($('<p>').text("Parsing " + file));