2

每次消息发出时,我的电信供应商都会向我发送报告。我编写了一个非常简单的 PHP 脚本,它通过 HTTP GET 接收值。使用 fwrite 我将查询参数写入 CSV 文件。文件名为 report.csv,以当前日期为前缀。

这是代码:

<?php
error_reporting(E_ALL ^ E_NOTICE);
date_default_timezone_set('America/New_York'); 
//setting a the CSV File
$fileDate = date("m-d-Y") ;
$filename = $fileDate."_Report.csv";

$directory = "./csv_archive/";

//Creating handle
$handle = fopen($filename, "a");

//These are the main data field
$item1 = $_GET['item1'];
$item2 = $_GET['item2'];
$item3 = $_GET['item3'];

$mydate = date("Y-m-d H:i:s") ;
$pass = $_GET['pass'];

//testing the pass
if (isset($_GET['pass']) AND $_GET['pass'] == "password")
    {
    echo 'Login successful';
    // just making sure the function could write to it
    if (!$handle = fopen($directory.$filename, 'a')){
         echo "Cannot open file ($filename)";
         exit;
    }

    //writing the data I receive through query string
    if (fwrite($handle, "$item1,$item2,$item3,$mydate \n") === FALSE) {
        echo "Cannot write to file ($filename)";
        exit;
    }

    fclose($handle); 
    }
else{
    echo 'Login Failure please add the right pass to URL';   
    }   
?>

该脚本执行我想要的操作,但唯一的问题是不一致,这意味着大部分记录丢失(大约一半的报告)。当我登录到我的帐户时,我可以获得完整的报告。

我不知道我需要做什么来解决这个问题,请指教。

4

1 回答 1

1

对于这个脚本,我有几个建议。

要解决 Andrew Rhyne 的建议,请将读取每个 $GET 变量的代码更改为:

$item1 = (isset($_GET['item1']) && $_GET['item1']) ? $_GET['item1'] : 'empty';

这将告诉您是否正在填充所有字段。

我怀疑你的问题是别的。听起来您对要保存的每条记录都有单独的请求。也许其中一些请求发生在一起关闭并且正在破坏彼此打开和写入文件的能力。要检查是否发生这种情况,您可以尝试使用以下代码检查您是否正确打开了文件。(请注意,您在脚本中第一次使用 'fopen' 没有任何作用,因为您在第二次使用 'fopen' 时覆盖了 $handle,它也打开了错误的文件......)

if (!$handle = fopen($directory.$filename, 'a')){
     $handle = fopen($directory.date("Y-m-d H:i:s:u").'_Record_Error.txt', 'a');
     exit;
}

这将确保您永远不会因为并发写入尝试而丢失数据。如果您发现这确实是您发出的,您可以延迟后续的写入尝试,直到文件不忙为止。

$tries = 0;
while ($tries < 50 && !$handle = fopen($directory.$filename, 'a')){
     sleep(.5);//wait half a second
     $tries++;
}
if($handle){
    flock($handle);//lock the file to prevent other requests from opening the file until you are done.
} else {
    $handle = fopen($directory.date("Y-m-d H:i:s:u").'_Record_Error.txt', 'a');//the 'u' is for milliseconds
    exit;
}

这将花费 25 秒,尝试每半秒打开一次文件,并且每次您仍然无法打开要写入的文件时,仍会将您的记录输出到一个唯一文件。然后,您可以像以前一样安全地 fwrite() 和 fclose() $handle。

于 2013-05-25T22:48:53.540 回答