Php 呈现pdf时执行两次Yii代码

Php 呈现pdf时执行两次Yii代码,php,pdf,yii,Php,Pdf,Yii,在我的页面上,人们可以选择在屏幕上查看pdf文件或下载它。以便在以后脱机时查看 当用户选择下载时,代码执行一次。我用一个计数器来跟踪它,每次下载它都会增加1。因此,该选项运行良好,可以在下面的if块中看到。 当用户选择查看该文件时,将显示pdf文件-这没关系-但每个视图的计数器将增加2。此代码从下面的else块运行 我还检查了Yii跟踪,它实际上是通过所有它两次,但只有当查看文件 if ($mode==Library::DOWNLOAD_FILE){ //DOWNLO

在我的页面上,人们可以选择在屏幕上查看pdf文件或下载它。以便在以后脱机时查看

当用户选择下载时,代码执行一次。我用一个计数器来跟踪它,每次下载它都会增加1。因此,该选项运行良好,可以在下面的if块中看到。 当用户选择查看该文件时,将显示pdf文件-这没关系-但每个视图的计数器将增加2。此代码从下面的else块运行

我还检查了Yii跟踪,它实际上是通过所有它两次,但只有当查看文件

      if ($mode==Library::DOWNLOAD_FILE){
        //DOWNLOAD
        Yii::app()->getRequest()->sendFile($fileName, @file_get_contents( $rgFiles[0] ) );
        Yii::app()->end();
      }
      else {
        //VIEW
        // Set up PDF headers
        header('Content-type: application/pdf');
        header('Content-Disposition: inline; filename="' . $rgFiles[0] . '"');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . filesize($rgFiles[0]));
        header('Accept-Ranges: bytes');

        // Render the file
        readfile($rgFiles[0]);
        Yii::app()->end();
      }
}

我尝试了一些其他选项,只是想看看它将如何使此运行两次:

从上面的代码中删除PDF标题时,计数器为 递增1,但我显然只在屏幕上看到垃圾。。。 如果我去掉readfile命令,计数器也会增加1, 但是浏览器不会呈现pdf,因为如果没有这一行,它将无法获取数据。。。 所以,只有当通过else块时,所有的Yii请求才会执行两次


提前感谢您的建议

我认为这是因为使用sendFile方法实际上只打开了一次文件,而在else分支中则打开了两次

在if分支中,使用file_get_内容打开文件一次,并将文件作为字符串传递给sendFile方法,然后计算该字符串的大小、输出标题等:

在else分支中,首先使用filesize打开文件,然后使用readfile方法打开文件

我认为您可以通过重写与sendFile方法类似的else分支来解决此问题:

基本上是用file_读入文件,将内容放入一个字符串,然后用mb_strlen计算这个字符串的长度。输出标题后,只需回显文件的内容,而无需重新打开它。 您甚至可以将整个sendFile方法复制粘贴到else分支中,只需在行中将附件更改为inline,或将整个if/else语句替换为sendFile方法,只需将attachment/inline选项更改为download或view,更优雅的方法是重写此方法并使用另一个参数进行扩展,要查看或下载给定文件,请执行以下操作:

所以我认为这样的解决方案是:

// open the file just once
$contents = file_get_contents(rgFiles[0]);

if ($mode==Library::DOWNLOAD_FILE){
    //DOWNLOAD
    // pass the contents of file to the sendFile method
    Yii::app()->getRequest()->sendFile($fileName, $contents);
} else {
    //VIEW
    // calculate length of file.
    // Note: the sendFile() method uses some more magic to calculate length if the $_SERVER['HTTP_RANGE'] exists, you should check it out if this does not work.
    $fileSize=(function_exists('mb_strlen') ? mb_strlen($content,'8bit') : strlen($content));

    // Set up PDF headers
    header('Content-type: application/pdf');
    header('Content-Disposition: inline; filename="' . $rgFiles[0] . '"');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . $fileSize);
    header('Accept-Ranges: bytes');

    // output the file
    echo $contents;
}
Yii::app()->end();
我希望这能解决你的问题,我的解释是可以理解的

// open the file just once
$contents = file_get_contents(rgFiles[0]);

if ($mode==Library::DOWNLOAD_FILE){
    //DOWNLOAD
    // pass the contents of file to the sendFile method
    Yii::app()->getRequest()->sendFile($fileName, $contents);
} else {
    //VIEW
    // calculate length of file.
    // Note: the sendFile() method uses some more magic to calculate length if the $_SERVER['HTTP_RANGE'] exists, you should check it out if this does not work.
    $fileSize=(function_exists('mb_strlen') ? mb_strlen($content,'8bit') : strlen($content));

    // Set up PDF headers
    header('Content-type: application/pdf');
    header('Content-Disposition: inline; filename="' . $rgFiles[0] . '"');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . $fileSize);
    header('Accept-Ranges: bytes');

    // output the file
    echo $contents;
}
Yii::app()->end();