提问人:Barbs 提问时间:10/22/2014 最后编辑:Barbs 更新时间:10/22/2014 访问量:788
PHP feof() 下载 - 网络错误
PHP feof() Download - Network Error
问:
我有一堆文件可供下载,我想通过登录来保护它们并隐藏路径以防止热链接。我正在使用 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文件(<1MB左右),这可以正常工作,但是对于我拥有的一些较大的ZIP文件(15-20MB),浏览器(在Chrome和Firefox中测试)抛出网络错误并在下载结束时失败。我认为这与这个位有关,但是更改缓冲区大小似乎没有任何影响?
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不喜欢这些较大的文件有关。
答:
不要以小块的形式读取文件,请尝试使用该函数。这将一次性读取整个文件。readfile()
所以改变这个
while(!feof($download)) {
$buffer = fread($download, 2048);
echo $buffer;
}
自
readfile($pathOnHd)
您也可以删除,因为这不是必需的,因为会自动打开和关闭文件。fopen()
readfile()
您的问题是输出缓冲。浏览器无法获取任何数据,而您回显读取字节。如果您使用的是输出缓冲,例如。ob_start() 你必须删除它。如果您不使用,那么它可能与服务器配置有关。PHP服务器范围的设置也可以强制执行。您可以通过 flush() 函数反转这一点。例:
while(!feof($download)) {
$buffer = fread($download, 2048);
echo $buffer;
flush();
}
如果这不起作用,您可能需要将 PHP 的output_buffering设置更改为 off。
PS:如果它真的很大,不要尝试用 fread() 读取整个文件。您的浏览器中会出现超时。
除了已经说过的内容外,不要使用 .与同名的 C 函数一样,它不会返回,直到您尝试读取文件末尾。该函数通过返回 来报告文件末尾,这是一个常见的习惯用语:feof
TRUE
fread
FALSE
while (($buffer = fread($download, 2048)) != FALSE) {
echo $buffer;
// flush output if needed
}
评论
echo file_get_contents($download)