首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP feof()下载-网络错误

PHP feof()下载-网络错误
EN

Stack Overflow用户
提问于 2014-10-22 16:17:46
回答 3查看 674关注 0票数 0

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

代码语言:javascript
复制
/**
* 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中测试)会抛出网络错误,并在下载结束时失败。我认为这与这一点有关,但更改缓冲区大小似乎没有任何影响?

代码语言:javascript
复制
while(!feof($download)) {
    $buffer = fread($download, 2048);
    echo $buffer;
}

有人能发现哪里出了问题吗?

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

代码语言:javascript
复制
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不喜欢这些大文件。

EN

回答 3

Stack Overflow用户

发布于 2014-10-22 16:27:48

不要以小块的形式读取文件,请尝试使用readfile()函数。这将一次性读取整个文件。

所以要改变这一点

代码语言:javascript
复制
while(!feof($download)) {
    $buffer = fread($download, 2048);
    echo $buffer;
}

代码语言:javascript
复制
readfile($pathOnHd)

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

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

票数 0
EN

Stack Overflow用户

发布于 2014-10-22 16:31:44

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

代码语言:javascript
复制
while(!feof($download)) {
    $buffer = fread($download, 2048);
    echo $buffer;
    flush();
}

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

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

票数 0
EN

Stack Overflow用户

发布于 2014-10-22 16:36:46

除了前面已经说过的之外,不要使用feof。与同名的C函数类似,在您尝试读取文件末尾之前,它不会返回TRUEfread函数通过返回FALSE来报告文件结束,这是一种常见的习惯用法:

代码语言:javascript
复制
while (($buffer = fread($download, 2048)) != FALSE) {
    echo $buffer;
    // flush output if needed
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26503040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档