заголовочный файл чтения на удаленном сервере PHP - PullRequest
0 голосов
/ 06 августа 2009

Мой сайт скачивает один файл, используя этот код:

$flv = **filename**

$ch = curl_init($flv);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch);

curl_close($ch);
if ($data === false) {
  echo 'cURL failed';
  exit;
}

$contentLength = 'unknown';
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
  $contentLength = (int)$matches[1];
}

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($flv));
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: ' . $contentLength );
ob_clean();
flush();
readfile($flv);

Код работает, но до тех пор, пока вы не закончите загрузку, ссылки на странице будут заблокированы, ожидая окончания загрузки!

Что я могу сделать?

Ответы [ 2 ]

1 голос
/ 06 августа 2009

попробуйте с:

$ContentLength = filesize($flv);

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($flv));
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: ' . $ContentLength);

$fh = fopen($flv, 'r');
echo fread($fh, $ContentLength);
fclose($fh);
1 голос
/ 06 августа 2009

Как вы ссылаетесь на эту страницу. Конечно, загрузка заблокирует все остальное на странице, так как при этом появится модальное окно, позволяющее пользователю выбрать, где загрузить файл или отменить загрузку. Это функция браузера.

Если вы говорите о чем-то еще, пожалуйста, объясните.


Edit:

На какую загрузку вы ссылаетесь? Здесь есть две загрузки. Одним из них является загрузка файла с сервера на сервер с использованием CURL. Другой - загрузка этого же файла HTTP-клиентом с вашего сервера. Оба могут быть «исправлены», но вы должны быть конкретными.

Если вы хотите, чтобы загрузка CURL была автоматической, то вы должны сделать эту загрузку отдельным процессом. К сожалению, PHP обычно поддерживает только один процесс, поэтому вы должны использовать нестандартный PHP.

Возможности:

1) Используйте оболочку

exec ('php filename.php downloadfile.ext &');

Здесь вы отправляете PHP-скрипт filename.php в качестве аргумента download.ext. Весь процесс будет выполняться в фоновом режиме из-за & в конце команды. Сделать var_dump ($ argv); чтобы увидеть аргументы переданы.

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

Например: poopen () proc_open ()

Они дают вам немного больше контроля.

2) Вы также можете установить одно из расширений управления процессом. http://php.net/manual/en/refs.fileprocess.process.php

Это позволит вам отделить отдельный процесс от вашего PHP-скрипта, который будет обрабатывать загрузку файла на ваш сервер. Существуют также расширения межпроцессного взаимодействия (IPC), которые позволят вам отслеживать, что происходит в отдельном процессе.

3) Вы можете написать демон для обработки загрузок. По сути, вам также нужно обрабатывать несколько процессов в вашем демоне, чтобы сделать несколько загрузок одновременно. Вам также понадобится немного IPC или хотя бы какая-то форма параллелизма, чтобы вы не загружали один и тот же ресурс более одного раза. Это становится немного сложнее, поэтому я думаю, что 1 и 2 являются лучшими вариантами.


По сути, вы пытаетесь не дать пользователю ждать загрузки сервера с сервера здесь.

Итак, вы начинаете с основного процесса PHP (обычная страница PHP). Затем вы как-то разветвляете процесс. Пусть этот дочерний процесс загрузит файл с помощью CURL. Тем временем родительский процесс PHP немедленно возвращается к клиенту HTTP. Когда дочерний процесс завершил загрузку, родительский процесс может узнать об этом через IPC или опросить параллельный ресурс, такой как имя файла (или размер файла, или блокировка) загруженного файла. Затем он передает это клиенту HTTP.


Если ваша проблема связана с HTTP-клиентом, вам придется искать решение в браузере. Учитывая конкретный браузер, с которым вы тестируете, и т. Д. И т. Д., Вы получите представление о проблеме.

...