2014-10-22 113 views
0

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

/** 
* 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文件(< 1MB左右)这工作得很好,但对于一些较大的ZIP文件我有(15-20MB)浏览器(测试中Chrome和Firefox)会引发网络错误,并在下载结束时失败。我认为这与这一点有关,但改变缓冲区大小似乎没有任何影响?

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

任何人都可以发现有什么问题吗?

编辑:试图从下面的回答以下...

注意:如果我赞同的路径,浏览器并粘贴在作为直接链接的文件下载OK。所以我对PHP不喜欢这些更大的文件做了些什么。

+0

不回答这个问题,不过,但如果15-20MB是国内规模较大的filesizes,为什么不使用' echo file_get_contents($ download)'而不是? – Repox 2014-10-22 08:22:36

+1

为什么不简单地使用[readfile()](http://www.php.net/manual/en/function.readfile.php)而不是循环和回显? – 2014-10-22 08:23:49

回答

0

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

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

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

ps:不要试图用fread()读取整个文件,如果它真的很大。你的浏览器中会有超时。

0

除了已经说过的内容之外,请不要使用feof。与C函数具有相同的名称一样,它不会返回TRUE,直到您试图读取过去的文件末尾。该fread功能通过返回FALSE报告结束文件,这是一个常见的成语:

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