PHP прокси для скачивания файлов - PullRequest
1 голос
/ 13 марта 2019

Я думаю, что это легко.

У меня есть простой веб-сайт с зарезервированной областью и некоторыми файлами для скачивания с нее.

Я отключил прямую загрузку файла с помощью .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.2GB-файл, который пользователи могут загрузить, и этот сценарий слишком медленный и не позволяет полностью загрузить файл.

Любая помощь будет принята,

Заранее спасибо!

M.

Ответы [ 4 ]

1 голос
/ 13 марта 2019

Вы можете использовать комбинацию header(), set_time_limit(), fgets(), ob_flush(), flush(). Вот мой пример, лучше всего использовать Php 64bit на OS 64bit, потому что filesize() не имеет ограничений в этой архитектуре.

    // 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;

Надеюсь, это поможет.

0 голосов
/ 19 марта 2019

Использовать ob_end_clean() до fpassthru($fp)

например

ob_end_clean();
fpassthru($fp);

Это может работать для больших файлов

0 голосов
/ 13 марта 2019

используйте 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=122&code=xxx&filename=xxxx", 302);
exit(0);

в луа:

parse the parameter ts and code, validate the code and ts value
proxy the file
0 голосов
/ 13 марта 2019

Используйте загрузку по частям, что-то вроде этого:

$chunkSize = 1024 * 1024;
while (!feof($fp))
{
    $buffer = fread($fp, $chunkSize);
    echo $buffer;
    ob_flush();
    flush();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...