呈现pdf时,Yii代码执行了两次

时间:2015-01-10 22:02:43

标签: php pdf yii

在我的页面上,人们可以选择查看pdf文件(在屏幕上)或下载它。 (稍后在他们离线时查看)

当用户选择下载时,代码会执行一次。我用计数器跟踪这个,每次下载都会增加1。所以,这个选项工作正常,可以在下面的if-block中看到 当用户选择查看文件时,会显示pdf文件 - 这样就可以了 - 但是对于每个视图,计数器会递增2。此代码从下面的else-block运行。

我还检查过" Yii trace"并且它实际上经历了两次,但仅在查看文件时...

      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-block时才会执行所有这些(Yii请求)执行两次...

提前感谢任何建议......

1 个答案:

答案 0 :(得分:0)

我认为这是因为使用sendFile()方法只打开文件一次,而在else分支中你实际打开它两次。

在if分支中,使用file_get_contents()打开文件一次,并将文件作为字符串传递给sendFile()方法,然后计算此字符串的大小,输出标题等:{ {3}}

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

我认为你可以通过重写类似于sendFile()方法的else分支来解决这个问题:

基本上将带有file_get_contents()的文件读入字符串,然后使用mb_strlen()计算此字符串的长度。输出标题后,只需回显文件内容而不重新打开它。 您甚至可以将整个sendFile()方法复制粘贴到else分支中,只需将中的“attachment”更改为“inline”(或者使用sendFile方法替换整个if / else语句,更改附件/内联选项以下载或查看,更优雅的方法是覆盖此方法并使用其他参数进行扩展,以查看或下载给定文件)

header("Content-Disposition: attachment; filename=\"$fileName\"");

所以我觉得这样的事情会成为一个解决方案:

// 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();

我希望这能解决你的问题,我的解释是可以理解的。