хм. В общем-то советы хорошие. но вся проблема в том что я использую рекурсию и файл нельзя скажем так сразу-же запихнуть в цикл и разобрать по частям(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();?>
Которая тоже не канает из-за рекурсии(
Сам механизм 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);
но это не приводит к скачке полного файла
И опять-же сокеты мне что-то не по нраву.
В общем как объяснить броузеру что для скачивания следующей части файла надо перейти по такому-то адресу(по тому-же самому) и что передадут с этого адреса прибавить к тому что уже скачано.... ППЦ хД---------- Добавлено 26.02.2013 в 15:26 ----------
Так так так, а по подробнее)
и как потом пользователь это все во едино соберет?) допустим будет 3 скачки по 500 килобайт хД) Ну да так то я могу))
Представьте вы скачиваете с сайта 3 части одного! файла и пытаетесь их собрать хДД
Руками))
Не, не, в хостере дело. Дело в модуле который пишу. Не все же пользователи имеют скажем так безграничные ресурсы на своих хостингах и прочем => значит надо максимально оптимизировать код под среднестатического юзеря, который не хочет портить себе нервы общением с хостером, а хочет просто Результат.
В итоге приходится оптимизировать код под стандартизированный конфиг сервера...
Мне не нравится хД) Я вообще такой изврат стараюсь нигде кроме денвера не применять - не знаю почему, наверное интуиция...
На самом деле я и планировал сделать примерно это, просто вышеуказанный кусок кода доказал свою работоспособность и я не заморачиваюсь теперь хД
Точно! сча попробую)---------- Добавлено 25.02.2013 в 15:52 ----------РАБОТАЕТ!!! Урааа)
Тестил вот этим:
single_rec(0);echo "sucess";function single_rec($i){ if($i<5){ sleep(20); return single_rec($i+1); }else return 0;}
Всем спасибо, уже написал хД Скоро буду рекурсию организовывать и прочие блага. Кому интересно писал по одкопанному где-то в глубинах гугла куску кода:
ссылка - http://marc.info/?l=php-general&m=117244455625774
Прошу прощения. Все вкурил тему)
Помогите плз. Пишу батч, такого вида:
function my_function_2(&$context) { $data = object_from_file(drupal_get_path('module', 'rmodule') . "/includes/data/authors.txt"); if (empty($context['sandbox'])) { $context['sandbox']['progress'] = 0; $context['sandbox']['max'] = count($data); } $limit = 1; if(empty($context['sandbox']['items'])) { $context['sandbox']['items'] = $data;//чо-то типа жизнь проходит мимо...(Витя Ак) } // Убираем из массива с данными уже обработанные материалы $counter = 0; foreach ($context['sandbox']['items'] as $item) { sleep(1);//чтобы быстро не мотало $file_patch = drupal_get_path('module', 'rmodule') . "/" . $item['img_url']; $file = (object) array( 'uid' => 1, 'status' => 1 ); $file->filename = basename($file_patch); $file->uri = $file_patch; //file_copy($file,"public://"); go_something($file); //$context['results'][] = $file_patch . ' : ' . $item['title']; $counter++; $context['sandbox']['progress']++; $context['message'] = $item['title']; $context['results']['processed'] = $context['sandbox']['progress']; } if ($context['sandbox']['progress'] != $context['sandbox']['max']) { $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; }}
И вот что вылазит
Вроде бы батч он на то и батч чтобы обходить Maximum execution time и прочую ерунду. Что делать? может я где-то не верно в коде написал?
big boy, http://drupalace.ru/lesson/obrabotka-bolshogo-kolichestva-dannyh-s-pomoshchyu-batch-api
Почитайте, как раз про изменение заголовка в нодах... Хотя это думаю слишком замудрено для такой задачи.
big boy, Если у вас пункт меню делается через хук hook_menu, то так можно присвоить кастомный заголовок к созданному пункту:
function mymodyle_menu() { $items = array(); $items['custom_manu'] = array(//ваш пункт меню 'title' => t('Бла бла бла'),//это не надо 'title callback' => 'mymodule_title',//тут делаем заголовок 'type' => MENU_CALLBACK, 'page callback' => 'кэллбэк функция', 'access arguments' => array('access content'), );return $items;}function mymodule_title(){/*Задаем тайтл для страницы поиска, ибо СЕО хД*/return t("Новый титле");}
Тут можно сделать так(у меня так)
function rmodule_audio_title(){/*Задаем тайтл для страницы поиска, ибо СЕО хД*/if(strlen(arg(1))!=0){return t("Поиск музыки по запросу:".arg(1));}elsereturn t("Фраза не найдена");}
Что хороше для сео. Если у вас к нодам отдельного типа надо прикрутить кастом ный заголовок то мы в одной тарелке, ибо так(хук node_view):
$node->content['body']['#object']->title = "Бла блы бла!";
Не хочет менять. Примерно то-же самое что и у меня, только с картинками.---------- Добавлено 08.02.2013 в 06:00 ----------Попробуйте hook_node_view_alter(&$call)
Тут можно вроде в массиве копнуть $call - там по любому есть
К слову - с картинками пытался так сделать - не катит. Хотя может мне просто взять и сделать так(говнокод детектед)
$tmp = implode(';',$call);str_replace(и поменть все элементы в которых встречается /sites/default/files/)$call = array();//обнулим$call = explode($tmp,";");
Сидя в бронированном танке танкисты нервно курили....