PHP PDF下载脚本正在执行两次

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了PHP PDF下载脚本正在执行两次脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个使用 PHP和PDO的Web应用程序和sqlSRV准备语句来显示文件链接用户下载.后端PHP脚本’download.PHP’在将PDF提供给用户下载之前检查各种项目.然后,download.PHP文件应更新几个sql表,并将PDF文件提供给用户.

请阅读我的
Previous Question
 如果您需要更多信息,可以在那里完成故障排除.

排除故障后,我认为发生的错误(因此我之前提出的问题)是不正确的.我的下载脚本每次下载文件都会被执行多次.

搜索服务器日志,在使用Firebug进行调试时,我可以看到我的download.PHP脚本向服务器发出多个GET请求.有时,脚本只按预期完成一次.其他时候,脚本执行三到四次请求,只需单击一次下载链接.

现在我更全面地了解发生了什么错误,我需要一些帮助来解决它.
我需要阻止脚本多次运行,从而使用彼此在几毫秒内的记录更新sql表.

视图页面检查sql数据库以查找当前用户可以访问的文件,并显示链接列表:

<a href='download.PHP?f={$ITem['name']}&amp;t={$tyPE}' target='_blank'>{$item['name']}</a>

因为download.PHP脚本需要使用这些值,所以我无法将请求更改为$_POST而不是$_GET.

我尝试过的:

>在退出(0)之前取消设置的getfile()之前检查/设置会话变量的“下载”状态
>将sql语句放在一个单独的PHP文件中并要求它
>在getfile()之后添加sleep(1)
>评论标题/ PDF信息

前三个措施无法阻止PHP下载脚本的双/三次执行.但是,最后一项措施是否会阻止PHP脚本的双重/三重执行,但当然PDF永远不会传送到客户端浏览器!

问题:如何确保只有一个插入/更新PER DOWNLOAD插入到数据库中,或者至少,如何PHP脚本多次执行?

UPDATE

firebug中的问题截图:

一个要求:

两个要求:

download.PHP脚本

<?PHP
session_start();

require("cgi-bin/auth.PHP");
// Don't timeout when downloading large files
@ignore_user_abort(1);  
@set_time_limit(0);  

//error_reporting(E_ALL); 
//ini_set('display_errors',1);

function getfile() {
    if (!isset($_GET['f']) || !isset($_GET['t'])) {
        echo "Nothing to do!";
        exit(0);
    }

    require('cgi-bin/connect_db_pdf.PHP');

    //Update VARiables
    $vuname = strtolower(trim($_SESSION['uname']));
    $file = trim(basename($_GET['f'])); //Filename we're looking for
    $type = trim($_GET['t']);//Filetype

    if (!PReg_match('/^[a-zA-Z0-9_\-\.]{1,60}$/',$file) || !preg_match('/^av|ds|cr|dp$/',$type)) {
        header('Location: error.PHP');
        exit(0);
    }

    try {
        $sQuery = "SELECT TOP 1 * From pdf_info WHERE PDF_name=:sfile AND type=:stype";
        $statm = $conn->prepare($sQuery);
        $statm->execute(array(':sfile'=>$file,':stype'=>$type));
        $result = $statm->fetchAll();
        $count = count($result);
        $sQuery = null;
        $statm = null;

        if ($count == 1 ){ //File was found in the database so let them download it. Update the time as well
            $result = $result[0];

            $sQuery = "INSERT INTO access (PDF_name,PDF_type,PDF_time,PDF_access) VALUES (:ac_file,:ac_type,GetDate(),:ac_vuname); UPDATE pdf_info SET last_view=GetDate(),viewed_uname=:vuname WHERE PDF_name=:file AND PDF_type=:type";

            $statm = $conn->prepare($sQuery);
            $statm->execute(array( ':ac_vuname'=>$vuname,':ac_file'=>$file,':ac_type'=>$type,':vuname'=>$vuname,':file'=>$file,':type'=>$type));
            $count = $statm->rowcount();
            $sQuery = null;
            $statm = null;


            //$result is the First element from  the SELECT query outside the 'if' scope.
            $file_loc = $result['floc'];
            $file_name = $result['PDF_name'];


            // Commenting from this line to right after the exit(0) updates the database only ONCE,but then the PDF file is never sent to the browser!
            header("Content-type: application/pdf"); 
            header("Pragma: no-cache");  
            header("Cache-Control: no-cache");  
            header("Content-Length: " . filesize($file_loc));  
            header("Accept-Ranges: bytes");
            header("Content-Disposition: inline; filename={$file_name}");  
            ob_clean();
            flush();
            readfile($file_loc);
            exit(0);


            } else { //We did not find a file in the database. redirect the user to the view page.
                header("Location: view.PHP");
                exit(0);
            }

            }   catch(PDOException $err) {//PDO sql error. 
            //echo $err;
            header('Location: error.PHP');
            exit(0);
         }

}

getfile();


?>

解决方法

如果您确实需要确保链接仅创建一次事件,那么您需要实现一个令牌系统,当生成链接(或表单发布目标)时,会生成并存储一次使用令牌(在会话或任何地方),然后在调用脚本中检查.

所以你的超链接可能如下所示:

<a href='download.PHP?token={some-token}&f={$item['name']}&t={$type}' target='_blank'>{$item['name']}</a>

PHP方面,这是一个非常简化的想法,你可能会做什么:

<?PHP
session_start();

if (!isset($_REQUEST['token']) die(); // or fail better
if (!isset($_SESSION['oneTimeTokens'][$_REQUEST['token']) die(); // or fail better
if ($_SESSION['oneTimeTokens'][$_REQUEST['token']=='used') die(); // or fail better
$_SESSION['oneTimeTokens'][$_REQUEST['token']='used';
// we're good from this point

这可以解决你的问题的影响,虽然不是双重运行本身.但是,既然你想确保一个链接只触发一次事件,那么你可能会以某种形式实现它,因为这是保证生成的任何链接都有一个我能想到的实际使用寿命的唯一方法. .

生成链接时,您可以在代码中执行以下操作:

<?PHP
$tokenID = {random id generation here};
$_SESSION['oneTimeTokens'][$tokenID] = 'not used';

我还会在某个地方放置一个清理例程来删除所有使用过的令牌.此外,超过一定年龄的令牌到期并不是一个坏主意,但我认为这解释了它.

脚本宝典总结

以上是脚本宝典为你收集整理的PHP PDF下载脚本正在执行两次全部内容,希望文章能够帮你解决PHP PDF下载脚本正在执行两次所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。