fopen — PHP feof () Загрузить — Ошибка сети

У меня есть куча файлов, доступных для скачивания, которые я хотел защитить с помощью входа в систему и скрыть путь для предотвращения хотлинкинга. Я использую сценарий PHP для этого (спасибо Майку Зриэлю за скрипт загрузки, я просто добавил свой собственный вызов базы данных и проверку входа пользователя).

/**
* 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 поменьше (<1 МБ или около того) это работает нормально, но для некоторых больших файлов ZIP (15-20 МБ) браузер (протестированный в 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, который не любит эти большие файлы.

0

Решение

Вместо того, чтобы читать файл небольшими блоками, попробуйте использовать readfile() функция вместо Это прочитает весь файл за один раз.

Так что измени это

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

к

readfile($pathOnHd)

Вы также можете удалить fopen() так как это не требуется, так как readfile() открывает и закрывает файл автоматически.

Увидеть руководство для отличного примера, который также имеет отношение к тому, что вы делаете

0

Другие решения

Ваша проблема в буферизации вывода. Браузер не может получить какие-либо данные, пока вы отображаете прочитанные байты. если вы используете буферизацию вывода, например. ob_start () вы должны удалить это. если вы не используете, то это может быть связано с конфигурацией сервера. Широкие настройки php-сервера тоже могут его заставить. Вы можете изменить это с помощью функций flush (). пример:

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

если это не работает, вам может потребоваться изменить настройку output_buffering в php на off.

ps: не пытайтесь читать весь файл с помощью fread (), если он действительно большой. у вас будет время ожидания в вашем браузере.

0

В дополнение к тому, что уже было сказано, не используйте feof, Как и функция C с тем же именем, она не возвращает TRUE пока не попробуешь читать прошлое конец файла. fread функция сообщает конец файла, возвращая FALSEи это распространенная идиома:

while (($buffer = fread($download, 2048)) != FALSE) {
echo $buffer;
// flush output if needed
}
0
По вопросам рекламы [email protected]