【问题标题】:PHP feof() Download - Network ErrorPHP feof() 下载 - 网络错误
【发布时间】:2014-12-17 15:25:12
【问题描述】:

我有一堆文件可供下载,我想通过登录来保护它们并隐藏路径以防止盗链。我正在使用 PHP 脚本来执行此操作(感谢 Mike Zriel 的下载脚本,我只是添加了自己的数据库调用和用户登录检查)。

/**
* Force file download and hide real Path
* @version        11.03.11 March 11, 2011
* @author         Mike Zriel, http://www.zriel.com
* @copyright      Copyright (C) 2010
* @license        http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
* @params     
*   filePath = Real Path of file
*   fileName = File Name
*/

//CHECK USER LOGIN
if(!isset($_COOKIE['login'])) {
echo "You are not authorised to download this file.";
exit;
} else {

include('database_connection.php');

//VALIDATE VARIABLES
if(isset($_GET['fileid'])) {
    if(!preg_match("/^\d+$/",$_GET['fileid'])) {
        echo "Invalid File ID.";
        exit;
    }
} else {
    echo "No File Specified.";
    exit;
}

try {
    $sql = $pdo->prepare("SELECT * FROM files WHERE id = ?");
    $sql->execute(array($_GET['fileid']));
    $array = $sql->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo "Error downloading file: ".$e->getCode();
}

if(!empty($array)) {
    $filePath = "http://www.example.com/PathToFile/";
    $fileName = $array['path']);
}

if(substr($filePath,-1)!="/") $filePath .= "/";

$pathOnHd = $filePath . $fileName;

if(isset($_GET['debug'])) {
echo "<br />".$pathOnHd;
}

if ($download = fopen ($pathOnHd, "br")) {

$size = filesize($pathOnHd);
$fileInfo = pathinfo($pathOnHd);
$ext = strtolower($fileInfo["extension"]);

switch ($ext) { 
case "pdf": 
header("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=\"{$fileInfo["basename"]}\"");
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"{$fileInfo["basename"]}\"");
}
header("Content-length: $size");

while(!feof($download)) {
    $buffer = fread($download, 2048);
    echo $buffer;
}
fclose ($download);
} else {
    echo "There was an error accessing the file: ".$array['name'].". <br />";
}
exit;
}

我遇到的问题是对于一些较小的 ZIP 或 PDF 文件(

while(!feof($download)) {
    $buffer = fread($download, 2048);
    echo $buffer;
}

谁能发现问题所在?

编辑:从下面的答案中尝试了以下...

readfile($pathOnHd); //Results in Unknown Network Error

while(!feof($download)) {
$buffer = fread($download, 2048);
echo $buffer;
flush();
}   //Not using ob_start() so not sure why this would change anything and it doesn't

while (($buffer = fread($download, 2048)) != FALSE) {
echo $buffer;
// Results in Unknown Network Error
}

注意:如果我回显浏览器的路径并将其粘贴为直接链接,则文件下载正常。所以我与 PHP 不喜欢这些大文件有关。

【问题讨论】:

  • 虽然没有回答这个问题,但是如果 15-20MB 是更大的文件大小,为什么不直接使用 echo file_get_contents($download) 呢?
  • 为什么不简单地使用readfile() 而不是循环和回显?

标签: php fopen feof


【解决方案1】:

尝试使用readfile() 函数代替小块读取文件。这将一次性读取整个文件。

所以改变这个

while(!feof($download)) {
    $buffer = fread($download, 2048);
    echo $buffer;
}

readfile($pathOnHd)

您也可以删除fopen(),因为这不是必需的,因为readfile() 会自动打开和关闭文件。

the manual for a great example that is also relevant to what you are doing

【讨论】:

    【解决方案2】:

    您的问题是输出缓冲。回显读取字节时,浏览器无法获取任何数据。如果您正在使用输出缓冲,例如。 ob_start() 你必须删除它。如果您不使用,则可能与服务器配置有关。 php 服务器范围的设置也可以强制它。您可以通过 flush() 函数来扭转这一点。示例:

    while(!feof($download)) {
        $buffer = fread($download, 2048);
        echo $buffer;
        flush();
    }
    

    如果这不起作用,您可能需要将 php 的 output_buffering 设置更改为关闭。

    ps:如果文件很大,不要尝试使用 fread() 读取整个文件。您的浏览器会出现超时。

    【讨论】:

      【解决方案3】:

      除了已经说过的,不要使用feof。与具有相同名称的 C 函数一样,它不会返回 TRUE,直到您尝试读取文件末尾过去fread 函数通过返回 FALSE 来报告文件结束,这是一个常见的习惯用法:

      while (($buffer = fread($download, 2048)) != FALSE) {
          echo $buffer;
          // flush output if needed
      }
      

      【讨论】:

        猜你喜欢
        • 2013-12-06
        • 2023-03-14
        • 2017-12-22
        • 1970-01-01
        • 1970-01-01
        • 2017-04-09
        • 2021-04-09
        • 1970-01-01
        • 2012-10-03
        相关资源
        最近更新 更多