Как скачать файл MP4 и скрыть путь URL с помощью PHP - PullRequest
0 голосов
/ 09 января 2019

У меня есть сайт, на котором пользователи должны платить за скачивание видео, которое они создают на сайте. Из-за этого мне нужно скрыть путь к загрузкам.

У меня есть страница php, где кнопка загрузки -

<form id="dl_script_form" action="dl-script.php" method="post" target="_blank">
<input name="userID" type="hidden" value="<?php echo $user->ID;?>" />
<input name="videosID" type="hidden" value="<?php echo $vId; ?>" />
<input name="downloadvids" id="downloadvids" type="submit" value="Download"/>
</form>

А на dl-script.php -

require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';

global $post;
$userid = $_POST['userID'];
$videosid = $_POST['videosID'];

$nameOld = '/path/to/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';
$nameNew = "download.mp4";
header('Content-type: video/mp4');
header("Content-disposition: attachment; filename=$nameNew");
header("Content-Length: ".filesize($nameOld));
readfile($nameOld);
exit(); 

При попытке нажать «Отправить» начинается загрузка (с именем файла download.mp4), но когда я пытаюсь открыть mp4 в Windows Media Player, он говорит мне -

Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.

Я проверил путь к файлу и смог без проблем воспроизвести видео в своем браузере или щелкнуть правой кнопкой мыши.

Так что с помощью php-скрипта файл должен быть как-то поврежден. Я пытался добавить / удалить header content-* и file_get_contents, но все равно не повезло.

Что я делаю не так?

РЕДАКТИРОВАТЬ

В целях тестирования я изменил код для загрузки со второго сервера на исходный сервер, с которого запускаю сценарий.

$userid = $_POST['userID'];
$videosid = $_POST['videosID'];

$path = 'https://path/to/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';
$save = '/var/path/to/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';

file_put_contents($save, fopen($path, 'r'));

$nameNew = "download.mp4";

header('Content-type: video/mp4');
header("Content-disposition: attachment; filename=$nameNew");
header("Content-Length: ".filesize($save));
readfile($save);

Это, однако, все еще не загружается правильно. Если я загружаю файл напрямую, хотя и без скрипта, он работает нормально.

Ответы [ 3 ]

0 голосов
/ 20 января 2019

Может ли быть какая-то проблема с обработкой https на стороне сервера? Вы пробовали простой http-запрос на второй сервер?

Вы когда-нибудь задумывались об использовании безопасных URL-адресов? Это может помочь снизить нагрузку на сеть и процессор на ваших серверах. Вместо того, чтобы скрывать реальный URL, вы можете дать пользователю временную ссылку, которая работает только для его IP (и истекает через некоторое время). Это то, что делают большинство сайтов с пробками. Проверьте это: http://nginx.org/en/docs/http/ngx_http_secure_link_module.html

0 голосов
/ 24 января 2019

Я не смог заставить его работать с любым из предложенных здесь советов, но, продолжив копать глубже, я смог заставить его работать.

Единственная проблема заключается в том, что мне нужно сохранить файл со второго сервера на мой первый сервер, чтобы загрузка работала. Затем я удаляю его, но я почти уверен, что это неэффективно с точки зрения производительности. Однако больше ничего я не пробовал работать.

Ключевая (ые) вещь (и), которая заставила его работать, это ob_start(), while (ob_get_level()) { ob_end_clean(); }

полный код -

ob_start();

$userid = $_POST['userID'];
$videosid = $_POST['videosID'];

$nameOld = 'https://path/to/get/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';
$save = '/path/to/save/it/'.$userid.'/'.$videosid.'/'.$videosid.'.mp4';

$nameNew = "download.mp4";

file_put_contents($save, fopen($nameOld, 'r'));

set_time_limit(0);

header('Connection: Keep-Alive');
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header("Content-Disposition: attachment; filename=$nameNew");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($save));

      while (ob_get_level()) {
        ob_end_clean();
      }

readfile($save);
exit;

// delete file when done
unlink($save);

Если кто-нибудь может предложить более эффективный пример кода, пожалуйста, продолжайте.

0 голосов
/ 16 января 2019

Сценарии выглядят отлично для того, что он делает.

Судя по комментариям, вы пытаетесь получить файл из удаленного местоположения, функция filesize не будет работать, вы должны найти другой способ получить размер файла или просто удалить его

способ получить размер файла через заголовки

следующий код должен получить размер файла из $nameOld удаленного местоположения

$headers= get_headers($nameOld, 1);
$filesize = $headers['Content-Length'];

get_headers () документация

readfile() поддерживает удаленные расположения файлов, но конфигурация allow_url_fopen php должна быть On


Для того, чтобы заставить его работать, вам нужно будет найти журнал ошибок, если отчет об ошибках равен error_reporting=E_ALL, тогда загружаемый вами файл содержит ошибку, поэтому, если вы откроете ее в текстовом редакторе, вы сможете чтобы увидеть ошибку, в противном случае выполните поиск в вашем файле error.log. Существуют значительные изменения в том, что allow_url_fopen не был настроен должным образом, но обнаружение ошибки поможет вам решить проблему.


Edit:

Я проверил ваш код и возможно загрузить образец mp4 из удаленного местоположения

$nameOld = 'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4';
$nameNew = "download.mp4";

$headers= get_headers($nameOld, 1);
$filesize = $headers['Content-Length'];

header('Content-type: video/mp4');
header("Content-disposition: attachment; filename=$nameNew");
header("Content-Length: ".$filesize);

readfile($nameOld);

если это не работает для вас, значит, проблема в настройках вашего сервера, вероятно, allow_url_fopen, о котором я упоминал ранее.

...