PHP - Javascript обновление информаии о файле

A4
На сайте с 05.01.2012
Offline
55
565

Здравствуйте уважаемые форумчане. Задача которую я пытаюсь решить выглядит примерно так:

Имеется файл размер которого изменяется с течением времяни(увеличивается).

Мы отправляем пользователю ссылку на первые 500 килобайт файла и догружаем остальное(таким образом ускоряется работа скрипта и уменьшается время ожидания пользователя).

То есть сначала загружается первая часть файла размером 500 килобайт и передается урл на эту часть. Потом размер файла меняется(он догружается fopen($file,"a+b")). Но у пользователя полуачется скачать только 500 кб, хотя ко времяни когда скачивание завершается размер файла увеличивается минимум в 2 раза.

Пробовал делать так:


header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $name);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $size);

Изначально мы знаем размер загружаемого файла - его размер $size

Но не смотря на то что этот размер мы и передаем в заголовках - скачиваются только первые 500кб((

Подскажите что делать, пожалуйста. Возможно кто-то уже сталкивался с такой проблеммой.

siv1987
На сайте с 02.04.2009
Offline
427
#1

Что мешает отдавать пользователю непрерывно по 500К без всяких извращений?

A4
На сайте с 05.01.2012
Offline
55
#2
siv1987:
Что мешает отдавать пользователю непрерывно по 500К без всяких извращений?

и как потом пользователь это все во едино соберет?) допустим будет 3 скачки по 500 килобайт хД) Ну да так то я могу))

Представьте вы скачиваете с сайта 3 части одного! файла и пытаетесь их собрать хДД

Руками))

siv1987
На сайте с 02.04.2009
Offline
427
#3
aftamat4ik:
и как потом пользователь это все во едино соберет?) допустим будет 3 скачки по 500 килобайт хД)

aftamat4ik, либо это 3 скачки по 500К либо это одна скачка по 500К, вы уж определитесь.

aftamat4ik:
Представьте вы скачиваете с сайта 3 части одного! файла и пытаетесь их собрать хДД

Склеить части задача для школьника, но вопрос в другом, что мешает отдавать в трех "пакетах" по 500К в один файл?

A4
На сайте с 05.01.2012
Offline
55
#4

В общем как объяснить броузеру что для скачивания следующей части файла надо перейти по такому-то адресу(по тому-же самому) и что передадут с этого адреса прибавить к тому что уже скачано.... ППЦ хД

---------- Добавлено 26.02.2013 в 15:26 ----------

siv1987:
Склеить части задача для школьника, но вопрос в другом, что мешает отдавать в трех "пакетах" по 500К в один файл?

Так так так, а по подробнее)

Оптимизайка
На сайте с 11.03.2012
Offline
396
#5
⭐ BotGuard (https://botguard.net) ⭐ — защита вашего сайта от вредоносных ботов, воровства контента, клонирования, спама и хакерских атак!
A4
На сайте с 05.01.2012
Offline
55
#6

хм. В общем-то советы хорошие. но вся проблема в том что я использую рекурсию и файл нельзя скажем так сразу-же запихнуть в цикл и разобрать по частям(time-limit, именно из-за него и применена рекурсия) Вот код самой функции(это druplal 7)


<?php
$url = "http://test1.ru/somefile.php";//собсна путь к файлу(он на самом деле слегка не так получается у меня)

if(isset($_GET['file_url']) && $_GET['i'] != $_GET["iter"]){//если в файл переданы GET параметры
$file_url = $_GET['file_url'];
$file_name = $_GET['file_name'];
$i = $_GET['i'];

cl_Read($file_url,$file_name.".mp3",512000*$i,512000);//закачиваем файл
$i++;

$ch = curl_init($url."/?file_url=".$file_url."&&iter=".$_GET['iter']."&&i=".$i."&&file_name=".$file_name);//продолжаем рекурсию
curl_setopt($ch, CURLOPT_TIMEOUT, 1);//ожидание ответа сервера - 1 сек. Можно было CURLOPT_TIMEOUT_MS, однако не на всех хостингах последняя версия CURL стоит...
curl_exec ($ch);
curl_close ($ch);
}
if(!isset($_GET['file_url']) && !isset($_GET['i'])){

$file_url = "http://somesite/somefolder/file.mp3";//отсюда качаем

$file_name = './audio/1.mp3';//сюда сохраняем

$fsize = curl_get_file_size($file_url);//получаем размер файла(на удаленном сервере) в килобайтах
$iter = round($fsize/512000) + 1;//число итераций рекурсивного цикла до полной закачки файла частями по 500 килобайт +1 ибо округлению я не доверяю....

cl_Read($file_url,$file_name,0,512000);//первая часть трека. ее мы после загрузки начинаем проигрывать, чтобы пользователя не бесить...

echo $file_name;//передаем урл - ссылку на файл для начала проигрывания, эту ссылку мы получаем в javascript'e и дальше в плеер ее в плеер!

$ch = curl_init($url."/?file_url=".$file_url."&&iter=".$iter."&&i=1&&file_name=".$file_name);//запускаем рекурсию $i = 1, так как первая часть трека уже скачана
curl_setopt($ch, CURLOPT_TIMEOUT, 1);//минимальное ожидание ответа сервера
curl_exec ($ch);
curl_close ($ch);
}

exit();
?>



---------- Добавлено 26.02.2013 в 20:59 ----------

Тут хорошая функция закачки файла блоками - http://stackoverflow.com/questions/6914912/streaming-a-large-file-using-php

Которая тоже не канает из-за рекурсии(

Сам механизм Chunked transfer encoding мне не до конца ясен. Я пытался сделать так(по этому совету - http://stackoverflow.com/questions/13565952/transfer-encoding-chunked-header-in-php-what-is-padding-for):



$url = "http://test1.ru/somefile.php";//собсна путь к файлу(он на самом деле слегка не так получается у меня)

if(isset($_GET['file_url']) && $_GET['i'] != $_GET["iter"]){//если в файл переданы GET параметры
$file_url = $_GET['file_url'];
$file_name = $_GET['file_name'];
$i = $_GET['i'];

cl_Read($file_url,$file_name.".mp3",512000*$i,512000);//закачиваем файл
$i++;

$ch = curl_init($url."/?file_url=".$file_url."&&iter=".$_GET['iter']."&&i=".$i."&&file_name=".$file_name);//продолжаем рекурсию
curl_setopt($ch, CURLOPT_TIMEOUT, 1);//ожидание ответа сервера - 1 сек. Можно было CURLOPT_TIMEOUT_MS, однако не на всех хостингах последняя версия CURL стоит...
curl_exec ($ch);
curl_close ($ch);
}
if(!isset($_GET['file_url']) && !isset($_GET['i'])){

$file_url = "http://somesite/somefolder/file.mp3";//отсюда качаем

$file_name = './audio/1.mp3';//сюда сохраняем

$fsize = curl_get_file_size($file_url);//получаем размер файла(на удаленном сервере) в килобайтах
$iter = round($fsize/512000) + 1;//число итераций рекурсивного цикла до полной закачки файла частями по 500 килобайт +1 ибо округлению я не доверяю....

cl_Read($file_url,$file_name,0,512000);//первая часть трека. ее мы после загрузки начинаем проигрывать, чтобы пользователя не бесить...
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $name);
header('Content-Transfer-Encoding: binary');
header('Content-Encoding', 'chunked');
header('Transfer-Encoding', 'chunked');
header('Content-Type', 'audio/mpeg');
header('Connection', 'keep-alive');


//echo $file_name;//передаем урл - ссылку на файл для начала проигрывания, эту ссылку мы получаем в javascript'e и дальше в плеер ее в плеер!

$ch = curl_init($url."/?file_url=".$file_url."&&iter=".$iter."&&i=1&&file_name=".$file_name);//запускаем рекурсию $i = 1, так как первая часть трека уже скачана
curl_setopt($ch, CURLOPT_TIMEOUT, 1);//минимальное ожидание ответа сервера
curl_exec ($ch);
curl_close ($ch);
}

exit();
?>

После этого при переходе на урл http://test1.ru/somefile.php начиналось скачивание файла и хотя размер файла изменился минимум 2 раза к концу закачки, скачалось всего 500кб. Что я не так делаю то?

Ну не могу я файл разбить на части как здесь(ссылка откуда взят код - выше):


$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}

while (!feof($fp)) {

echo fgets($fp, 128);

}

- не применимо! можно сделать так:

if(!eof($fp)) echo fgets($fp, 128);

но это не приводит к скачке полного файла

И опять-же сокеты мне что-то не по нраву.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий