#php #proxy #download-manager #source-code-protection
#php #прокси #менеджер загрузок #защита исходного кода
Вопрос:
Я думаю, что это очень просто.
У меня есть простой веб-сайт с зарезервированной областью и некоторыми файлами для загрузки с него.
Я отключил прямую загрузку файлов с помощью .htaccess, и я управляю загрузкой файла с помощью этого простого proxy.php файл:
// ....
if ($filename === null || !file_exists($proxiedDirectory.$filename)) {
http_response_code(404);
exit;
}
if (!$site->is_logged_in()) {
http_response_code(403);
exit;
}
$fp = fopen($proxiedDirectory.$filename, 'rb');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
fpassthru($fp);
exit;
Этот код РАБОТАЕТ отлично, но, к сожалению, у меня есть файл объемом 1,2 Гб, который пользователи могли бы загрузить, а этот скрипт работает слишком медленно и не позволяет загрузить файл полностью.
Буду признателен за любую помощь,
Заранее спасибо!
M.
Ответ №1:
Вы можете использовать комбинацию header()
, set_time_limit()
, fgets()
ob_flush()
, flush()
filesize()
. Вот мой пример, лучше всего использовать 64-битный Php на 64-битной ОС, потому что в этой архитектуре нет ограничений.
// Set force download headers
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $file . '"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . sprintf("%u", filesize($downloads_folder . $file)));
// Open and output file contents
set_time_limit(0);
$fh = fopen($downloads_folder . $file, "rb");
while (!feof($fh)) {
echo fgets($fh);
ob_flush();
flush();
}
fclose($fh);
exit;
Надеюсь, это поможет.
Ответ №2:
Используйте фрагментированную загрузку, что-то вроде этого:
$chunkSize = 1024 * 1024;
while (!feof($fp))
{
$buffer = fread($fp, $chunkSize);
echo $buffer;
ob_flush();
flush();
}
Ответ №3:
использование nginx в качестве прокси может быть более подходящим. Причина проста: когда вы загружаете с помощью php, при запросе в php-fpm будет время ожидания, поэтому файл, скорее всего, не сможет быть загружен полностью.
location /proxy.lua {
proxy_pass http://proxy.com/link/;
}
если вам нужно проверить, есть у пользователя логин или нет, вы можете использовать lua nginx (OpenResty)
тем не менее, есть простой способ проверить это: 1. proxy.php перенаправьте запрос на nginx location proxy.lua с двумя параметрами: ts и code.
ts is timestamp of server
code is md5sum(ts "complexstring")
header("Location: /proxy.lua?ts=122amp;code=xxxamp;filename=xxxx", 302);
exit(0);
когда в lua:
parse the parameter ts and code, validate the code and ts value
proxy the file
Комментарии:
1. Спасибо, Райан, ваш ответ правильный, но, к сожалению, у меня общий хост apache : (
2. вы можете перенаправить запрос на какой-нибудь хост, которым является nginx или openresty. Когда прокси для большого файла или клиентской сети работает недостаточно быстро, обязательно произойдет тайм-аут.
Ответ №4:
Используйте ob_end_clean()
перед fpassthru($fp)
например
ob_end_clean();
fpassthru($fp);
Это может сработать для больших файлов