Просмотр полной версии : Автоматичная закачка файла - альтернатива FTP ?
^_WhitE_DeMoN_^
30.04.2010, 05:13
Таак, написал automatic remote backup tool, PHP скрипт дампит MySQL базы, записывает их локально и закачивает на удаленный FTP...
Только вот проблем...
Хост ругается: ftp_put() [function.ftp-put]: php_connect_nonb() failed: Operation now in progress (115) (2)
Саппорт отвечает: We do not allow the FTP functions to be used against remote FTP servers.
Так вот ищу простую альтернативу ftp_*, есть идея передавать имя файла (которое генерируется разное!) GET запросом удаленному скрипту, а тот скачает и запишет файл.
Но как реализовать, вообще не думается :confused:
Буду благодарен за куски кода, примеры, обяснения...
Спасибо что дочитали :D
Ну например так:
1 хост, который делает дамп:
<?php
/*
{
Тут делаешь дамп и сораняешь файл локально
}
*/
$damp_file = "db.sql"; //Тут имя файл который сдампился
echo file_get_contents("http://my_server_2/saver.php?file=".$damp_file); //Тут ты передаешь хосту №2 какой файл ему скачивать
?>
Хост №2 который скачивает
<?php
$server_1 = "http://server_nomer_1/"; //Тут адрес сервера откуда скачивать
$dump_file = $_GET['file'];
$file_prefix = "saved_";
if(file_put_contents($file_prefix.$dump_file,file_ get_contents($server_1.$dump_file))) {
echo "File_saved!";
}else echo "File dont saved";
?>
Ну впринципе и все. 1 скрипт напишет File_saved! если файл успешно скачен вторым сервером. На втором сервере появится файл saved_db.sql
Ну думаю схема понятна. )))
Если файл большой, то во втором скрипте скачивай "побайтово".
функция fread()
//практикуем убийство серверов?)))
^_WhitE_DeMoN_^
30.04.2010, 17:58
Ожидается что будет большой, и еще 50 штук таких... Базы phpBB3 =)
Иначе все понятно, спасибо огромное, щас в репу стукну
Няя, я не убиец =) Я наемный убиец =) ...а так, сайто строитель...
Deathdreams
30.04.2010, 22:50
скрипт, который дампит (в переменной $server указать путь до скрипта, который скачивает):
<?php
/*тут дамп в переменную $dump*/
$server = 'http://fsdfdsf.ru/example.php'; //путь до второго файла
@ini_set('max_execution_time', 0);
$name = "dump".date("YmdHis").".sql";
if( @file_put_contents( $name, $dump ) )
{
echo 'Сохранили дамп...'.PHP_EOL;
$path = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].$name;
$content = file_get_contents( $server.'?put='.urlencode($path) );
if( $content == 'success' ) echo 'Сервер успешно сохранил наш дамп.'.PHP_EOL;
else echo 'Серверу не удалось сохранить наш дамп.'.PHP_EOL;
} else echo 'Дамп сохранить не удалось. Проверь chmod.';
?>
скрипт для сохранения дампа:
<?php
$dir = '/dumps/'; //папка с дампами
$file = "http://".stripslashes(urldecode(trim($_GET['put'])));
if( file_put_contents( $dir."dump".date("Y-m-d+H-i-s"), file_get_contents($file) ) )
{
die('success');
} else die('false');
?>
/*писалось на скорую руку, подправьте если что не так*/
^_WhitE_DeMoN_^ если блокируются только функции ftp_*, напишите свой класс на сокетах, благо FTP - простейший протокол
Или еще проще: file_put_contents("ftp://user:password@ftp.server.ru/file.txt", file_get_contents('имя_локального_ф йла'));
^_WhitE_DeMoN_^
02.05.2010, 02:56
Или еще проще: file_put_contents("ftp://user:password@ftp.server.ru/file.txt", file_get_contents('имя_локального_ф йла'));
Удивил, проще некуда! Но, пока сделал первый вариант... И хз че еще у хостера запрещенно ;)
^_WhitE_DeMoN_^
09.05.2010, 01:39
Ну например так:
1 хост, который делает дамп:
<?php
/*
{
Тут делаешь дамп и сораняешь файл локально
}
*/
$damp_file = "db.sql"; //Тут имя файл который сдампился
echo file_get_contents("http://my_server_2/saver.php?file=".$damp_file); //Тут ты передаешь хосту №2 какой файл ему скачивать
?>
Хост №2 который скачивает
<?php
$server_1 = "http://server_nomer_1/"; //Тут адрес сервера откуда скачивать
$dump_file = $_GET['file'];
$file_prefix = "saved_";
if(file_put_contents($file_prefix.$dump_file,file_ get_contents($server_1.$dump_file))) {
echo "File_saved!";
}else echo "File dont saved";
?>
Ну впринципе и все. 1 скрипт напишет File_saved! если файл успешно скачен вторым сервером. На втором сервере появится файл saved_db.sql
Ну думаю схема понятна. )))
Если файл большой, то во втором скрипте скачивай "побайтово".
функция fread()
//практикуем убийство серверов?)))
Хост ругается:
file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration (2)
Идеи :confused:
^_WhitE_DeMoN_^
12.05.2010, 03:26
У никого ?
У никого ?
Помоему, вот этот параметр в php.ini
allow_url_fopen=on;
^_WhitE_DeMoN_^
12.05.2010, 10:11
Нет доступа к php.ini
Ищу обход...
ghostwizard
12.05.2010, 17:39
Обязательно ftp ?
1. Пробуй через сокеты, если не запрещено.
2. Напрямую через 80-й порт.
Нет доступа к php.ini
Ищу обход...
ini_set();
или читай через сокет
http://ru2.php.net/manual/en/function.fsockopen.php
^_WhitE_DeMoN_^
13.05.2010, 19:39
FTP - не обязательно.
Нужно только реализовать закачку файла с одного сервера на другой, а как ето уже проблем... Со сокетами не знаком, но придется доки курить...
ini_set('allow_url_fopen', 'On'); не помогло...
^_WhitE_DeMoN_^
17.05.2010, 10:47
И через сокеты не пашет - URL file-access is disabled in the server configuration (2)
Другие идеи..?
roxblnfk
17.05.2010, 11:25
слать через POST, если файлы большие (или ограничение на POST), то кусками с указанием сегментов :)
вначале сделать запрос на передачу файла, в POST параметрах указать имя файла, логин/пароль, хэш всего файла, его размер.
Далее, получив согласие получателя и код сессии начинаем передавать сегменты файла:
указать только начало, конец, контрольную сумму (на всякий) обрывка; сессию на файл
Принимающий собирает по кускам, проверяет получившуюся контрольную сумму и всё.
Ну и написать проверку, что если были ранее начаты сессии с незаконченными передачами, которые не обновлялись более часа, то их стоит удалить.
куски файла можно зипировать..
а если и в base64 закодировать, то можно и GET-ом передать xD правда там на заголовки больше уйдёт трафика, но система будет работать :D
^_WhitE_DeMoN_^
17.05.2010, 22:35
Вообще не врубил...
а если и в base64 закодировать, то можно и GET-ом передать
При base64 строка увеличиться в несколько раз, а метод GET при отправки большого количества данных какбе не лучший вариант.
^_WhitE_DeMoN_^, Ты сокетами, надеюсь, отправлял заголовки?
roxblnfk
17.05.2010, 23:41
При base64 строка увеличиться в несколько раз, а метод GET при отправки большого количества данных какбе не лучший вариант.
^_WhitE_DeMoN_^, Ты сокетами, надеюсь, отправлял заголовки?
я об этом и говорю, что заголовки ппц будут :)
^_WhitE_DeMoN_^, написл для тебя функцию с коментами. Если не новиш в php, то дальше сам разрулишь
(функцию можешь не изучать, просто используй как надо, хотя в ней многое не учтено, но для простых запросов хватит)
function HTTP_request($serv='127.0.0.1', $port=80, $timeout=30, $host='localhost', $addr='/index.php', $post=null, $cookies=null){
$str='';$heads='';
if(is_array($post))if(count($post)>0){
$method='POST';
$str.="\r\n\r";
foreach($post as $k=>$v){
$str.='&'.$k.'='.urlencode($v);
}
$str{4}="\n";
$heads.="\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ".(strlen($str)-4);
}
if(!isset($method)){
$method='GET';
//$heads.="\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$str="\r\n\r\n";
}
if(is_array($cookies))if(count($cookies)>0){
$cook="\r\nCookie: ";
foreach($cookies as $k=>$v){$cook.=$k.'='.urlencode($v).'; ';}
$heads.=substr($cook,0,-2);
}
if(false!=($f=@fsockopen($serv, $port, $errno, $errstr, $timeout))){
$ss='';
fputs ($f, "$method $addr HTTP/1.1".$heads."\r\nHost: $host\r\nConnection: close".$str);
while (!feof($f)) {
$ss.=fgets($f, 512);
}
fclose($f);
}else return array(false, $errstr);
return array(true, $ss);
} // вернёт массив 0=>сокет сконнектил 1=> если не сконнектил, то текст ошибки, иначе овтет сервера
//////////////////////////
//////
$serv='127.0.0.1'; // IP или домен сервера
$port=80; // порт
$host='localhost'; // Что передавать в заголовке HOST
$addr='/index.php';// Адрес до страницы на сайте
$timeout=30; // таймаут соединения
$post=array(); // массив с переменными в формате ($var1 => $value1, $var2 => $value2...) {в $var# желательно использовать только латину}
$cookie=array();// cookies заполняется аналогично $post
print_r(HTTP_request($serv, $port, $timeout, $host, $addr, $post, $cookie));
ini_set('allow_url_fopen', 'On'); не помогло...
kuri htaccess
^_WhitE_DeMoN_^
20.05.2010, 01:52
@LStr1ke, неа...
@roxblnfk, возвращает "1" =(
@|qbz|, и .htaccess не прокатил...
roxblnfk
20.05.2010, 14:40
^_WhitE_DeMoN_^, ошибка есть, тут: $str{4}="\n";
надо $str{3}="\n";
А где возвращает 1? :)
я тут RFC протокола перечитал, увидел следующее на счёт Content-Length:
Длина тела объекта (entity-body) - это длина тела сообщения (message-body), полученного после декодирования всех кодирований передачи.
Т.е., как я понял, сюда надо вписывать не длину закодированного контента, а длину контента до кодирования. В нэте в примерах показывают обратное, т.е. указывают длину закодированного контента.
Вобщем немного переделал функцию (тут длина до кодирования):
function HTTP_request($serv='127.0.0.1', $port=80, $timeout=30, $host='localhost', $addr='/', $post=null, $cookies=null){
$str='';$heads='';
if(is_array($post))if(count($post)>0){
$method='POST';
$str.="\r\n\r";
$Len=0;
foreach($post as $k=>$v){
$str.='&'.$k.'='.urlencode($v);
$Len+=2+strlen($k)+strlen($v);
}
$Len-=1;
$str{3}="\n";
$heads.="\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ".$Len;
}
if(!isset($method)){
$method='GET';
//$heads.="\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$str="\r\n\r\n";
}
if(is_array($cookies))if(count($cookies)>0){
$cook="\r\nCookie: ";
foreach($cookies as $k=>$v){$cook.=$k.'='.urlencode($v).'; ';}
$heads.=substr($cook,0,-2);unset($cook);
}
if(false!=($f=@fsockopen($serv, $port, $errno, $errstr, $timeout))){
$ss='';
fputs ($f, "$method $addr HTTP/1.1".$heads."\r\nHost: $host\r\nConnection: close".$str);
while(!feof($f)){$ss.=fread($f, 512);}
fclose($f);
}else return array(false, $errstr);
return array(true, $ss);
}
надеюсь в Content-Length учитываются разделители и названия переменных :)
Кстати, чтобы передавать бинарные данные, лучше использовать MIME без всякого кодирования. Этим же способом передают фотки с текстом за 1 раз. С момента прошлого поста я успел написать функцию, реализующую MIME в POST, только не закончил. В функции нет возможности аутентификации (Digest Authentication), но эти заголовки несложно дописать вручную. Если надо, могу поделиться.
^_WhitE_DeMoN_^
21.05.2010, 00:42
А где возвращает 1? :)
Сдесь:
echo tpl_l(print_r(HTTP_request($serv, $port, $timeout, $host, $addr, $post, $cookie)), C_RESULT);
Вот из за какогото [censored] и его [censored] настройки сервака, должен извращатся а не радоватся file_get_contents()
Ну никак не пашет !
Да сделай по изврату ) Обычно, когда делать совсем нех. пользуешься извратом )
Короче )
На сайте, где хочешь сохранить файл (куда закачивать) делаешь форму, ну обычную, типа закачать файл.
<?php
if($_FILES["filename"]["name"] == null) {
echo "NO FILE";
exit;
}
if(copy($_FILES["filename"]["tmp_name"],
$_SERVER['DOCUMENT_ROOT']."/".$_FILES["filename"]["name"]))
{
echo "OK";
} else {
echo "ERROR";
}
?>
А на сервере, откуда заливать файл (базу) делаешь токой скрипт:
<?php
$file = "baza.sql"; // Должен лежать в каталоге со скриптом
$post_data = '-----------------------------01010
Content-Disposition: form-data; name="filename"; filename="'.$file.'"
-----------------------------01010
Content-Type: application/octet-stream
'.file_get_contents('baza.sql').'
-----------------------------01010--';
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://server.ru/upload.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_HTTPHEADER,array (
"Content-Type: multipart/form-data; boundary=---------------------------01010",
));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_REFERER, 'http://server.ru/test.html');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post_data);
$result = curl_exec($ch);
echo $result;
?>
И если все замечательно, то скрипт покажет OK и сохранит файл в server.ru/files/
Ну это конечно извращенно, вообщем хз, что еще посоветовать )
roxblnfk
21.05.2010, 15:13
Сдесь:
echo tpl_l(print_r(HTTP_request($serv, $port, $timeout, $host, $addr, $post, $cookie)), C_RESULT);
эм.. что за echo tpl_l();
HTTP_request() вернёт МАССИВ, где первый элемент с ключем 0 будет true или false, второй элемент с индексом 1 — текст ошибки (в случае, если первый false) или ответ сервера (если первый элемент - true, т.е. коннект удался)
присвой значение переменной и бери условие...
$Result=HTTP_request();
if($Result[0]){
echo "запрос отправил, вот ответ:\r\n".$Result[1];
}else{
echo "Не удалось соедениться с сервером, вот текст ошибки:\r\n".$Result[1];
}
...ты думаешь, что админы дурачки и отключив сокеты и урл_фопен оставили работать курл? ну-ну
roxblnfk
22.05.2010, 00:16
^_WhitE_DeMoN_^,
написал передачу файла по посту по кускам (ограничение размера файла - 2 гига ровно минус 1 байт)
Да и пост у меня по кускам :) собирай..
function pro_HTTP_($SOCKET, $HEAD, &$CONTENT){
$SOCKETs=array(
'Socket-Address'=>'localhost',
'Socket-Port'=>80,
'Socket-Timeout'=>10,
'Socket-DownLimit'=>null // null-без лимита
);
$HEADs=array(
// САМЫЕ ОСНОВНЫЕ :)
'Method'=>null, // если не указано, устанавливается автоматически GET или POST [GET POST PUT OPTIONS HEAD DELETE PATCH TRACE LINK UNLINK]
'URI'=>'/',
'HTTP'=>'HTTP/1.1',
// ОСНОВНЫЕ // Знак ? означает, что заголовок не фильтруется и всё, что вы через него передадите, выведется в чистом виде
// Формат даты (пример): Sun, 06 Nov 1994 08:49:37 GMT
'Cache-Control'=>null, //? Основные директивы для управления кэшированием.
'Connection'=>false, // Сведения о проведении соединения // false=Close;true=Keep-Alive;если число, то добавляется Keep-Alive: с этим числом
'Date'=>null, //? Дата генерации отклика.
'MIME-Version'=>null, //? Версия протокола MIME по которому было сформировано сообщение.
'Pragma'=>null, //? Особенные опции выполнения операции.
'Trailer'=>null, //? Список полей, имеющих отношение к кодированию сообщения при передаче.
'Transfer-Encoding'=>null, //? Список способов кодирования, которые были применены к сообщению для передачи.
'Upgrade'=>null, //? Список предлагаемых клиентом протоколов. Сервер указывает один протокол.
'Via'=>null, //? Список версий протокола, названий и версий прокси-серверов через которых прошло сообщение.
'Warning'=>null, //? Код, агент, сообщение и дата если возникла критическая ситуация.
// ЗАПРОС
'Accept'=>null, // Список допустимых форматов ресурса.
'Accept-Charset'=>null, //? Перечень поддерживаемых кодировок для предоставления пользователю
'Accept-Encoding'=>null, //? Перечень поддерживаемых способов кодирования содержимого сущности при передаче.[gzip,deflate],compress,x-gzip,x-compress
'Accept-Language'=>null, // Список поддерживаемых естественных языков.
/* */ 'Authorization'=>null, //! Данные для авторизации.
'Expect'=>null, //? HTTP/1.1v2 Указывает серверу что клиент ожидает от него дополнительного действия.
'From'=>null, // Адрес электронной почты ответственного лица со стороны клиента.
'Host'=>true, // Доменное имя и порт хоста запрашиваемого ресурса. Необходимо для поддержки виртуального хостинга на серверах.// Если true, то заполняется из сокета
'If-Match'=>null, //? Список тегов версий сущности. Выполнять метод если они существуют.
'If-Modified-Since'=>null, //? Дата. Выполнять метод если сущность изменилась с указанного момента. Используется только для метода обработки GET
'If-None-Match'=>null, //? Список тегов версий сущности. Выполнять метод если ни одного из них не существует.
'If-Range'=>null, //? Список тегов версий сущности или дата для определённого фрагмента сущности.
'If-Unmodified-Since'=>null, //? Дата. Выполнять метод если сущность не изменилась с указанной даты.
'Max-Forwards'=>null, //? Максимально допустимое количество переходов через прокси.
/* */ 'Proxy-Authorization'=>null, //! Информация для авторизации на прокси-сервере.
'Range'=>null, // Байтовые диапазоны для запроса фрагментов ресурса. Подробности: Частичные GET. [bytes=64397516-80496894]
'Referer'=>null, // URI ресурса, после которого клиент сделал текущий запрос.// если true, то берётся из адреса
'TE'=>null, //? HTTP/1.1v2 Список расширенных способов кодирования при передаче.
'User-Agent'=>null, //? Список названий и версий клиента и его компонентов с комментариями.
// СОДЕРЖИМОЕ (СУЩНОСТИ) CONTENT
'Content-Disposition'=>null, //? Способ распределения сущностей в сообщении при передачи нескольких фрагментов.
'Content-Encoding'=>null, //? Способ кодирования содержимого сущности при передаче.
'Content-Language'=>null, // Один или несколько естественных языков содержимого сущности
'Content-Length'=>null, // Размер содержимого сущности в байтах. // если передаётся в $CONTENT, то будет заполнено автоматически, лучше не трогать
'Content-Location'=>null, //? Альтернативное расположение содержимого сущности.
'Content-MD5'=>null, //?!MD5-хэш сущности для проверки целостности. // для автоматического заполнения перевести в ture
'Content-Range'=>null, //? Байтовые диапазоны передаваемой сущности если возвращается фрагмент. Подробности: Частичные GET.
'Content-Type'=>null, // Формат и способ представления сущности.
'Content-Version'=>null, //? Информация о текущей версии сущности.
'Derived-From'=>null, //? Информация о текущей версии сущности.
'Last-Modified'=>null, //? Дата последней модификации сущности.
'Link'=>null, //? Указывает на логически связный с сущностью ресурс аналогично тегу <LINK> в HTML.
'Title'=>null //? Заголовок сущности.
);
foreach($SOCKETs as $k=>$v){ if(isset($SOCKET[$k])) $SOCKETs[$k]=$SOCKET[$k]; }
$keys=array_keys($HEADs);
$lim=count($keys);
for($i=0;$i<$lim;$i++){
$Head=$keys[$i];
$Value=$HEADs[$Head];
if(isset($HEAD[$Head])){ if($HEAD[$Head]!=='') $HEADs[$Head]=$HEAD[$Head]; }
elseif(is_null($Value)) unset($HEADs[$Head]);
}
if((string)$HEADs['URI']=='') $HEADs['URI'] ='/'; else $HEADs['URI'] =(string)$HEADs['URI'];
if((string)$HEADs['HTTP']=='') $HEADs['HTTP']='HTTP/1.1'; else $HEADs['HTTP']=(string)$HEADs['HTTP'];
if($HEADs['Connection']){
if(is_numeric($HEADs['Connection'])) $HEADs['Keep-Alive']=intval($HEADs['Connection']);
$HEADs['Connection']='Keep-Alive';
}else $HEADs['Connection']='Close';
if(isset($HEADs['Host'])){ if($HEADs['Host']===true || strlen($HEADs['Host'])==0)$HEADs['Host']=$SOCKETs['Socket-Address']; }
if(isset($HEADs['Referer'])) if($HEADs['Referer']===true) $HEADs['Referer']=$HEADs['URI'];
$Content='';
if(isset($CONTENT)) if(is_array($CONTENT)){
if(isset($CONTENT)) if(isset($CONTENT['POST'])) if(is_array($CONTENT['POST'])) if(count($CONTENT['POST'])>0){
$HEADs['Method']='POST';$MIME=false;
$keys=array_keys($CONTENT['POST']);$lim=count($keys);
for($i=0;$i<$lim;$i++){ if(is_array($CONTENT['POST'][$keys[$i]])){ $MIME=true; break; } }
$Length=0;
if($MIME){
$boundary= substr(sha1(md5(mktime())), 4, -4);
$boundary= $boundary.strtoupper(md5($boundary)); $boundary{10}='+'; $boundary{12}='_'; //получение более-менее уникальной границы
$HEADs['Content-Type']='multipart/form-data; boundary="'.$boundary.'"';
foreach($CONTENT['POST'] as $Keyko=>$Postec){
if(is_array($Postec)){
$Content.="--$boundary\r\nContent-Disposition: form-data";
if(isset($Postec['name'])) $Content.='; name="'.$Postec['name'].'"'; else $Content.='; name="'.$Keyko.'"';
if(isset($Postec['filename']))$Content.='; filename="'.$Postec['name'].'"';
$Content.="\r\n";
foreach($Postec as $K=>$V){ if($K!='' && $K!='name' && $K!='Content-Disposition') $Content.="$K: $V\r\n"; }
$Content.="\r\n".@$Postec['']."\r\n";
}else $Content.="--$boundary\r\nContent-Disposition: form-data; name=\"$Keyko\"\r\n\r\n$Postec\r\n";
}
$Content.="--$boundary--";
$Length=strlen($Content);
}else{
foreach($CONTENT['POST'] as $k=>$v){
$Content.=trim($k).'='.urlencode($v).'&';
$Length+=2+strlen(trim($k))+strlen($v);
}
$Length-=1;
$Content=substr($Content,0,-1);
$HEADs['Content-Type']='application/x-www-form-urlencoded';
}
if(isset($HEADs['Content-Length'])) if($HEADs['Content-Length']===true) $HEADs['Content-Length']=$Length;
if(isset($HEADs['Content-MD5'])) if($HEADs['Content-MD5']===true) $HEADs['Content-MD5']=md5($Content);
}
// cookie
if(isset($CONTENT)) if(isset($CONTENT['Cookie'])) if(is_array($CONTENT['Cookie'])) if(count($CONTENT['Cookie'])>0){
$HEADs['Cookie']='';
foreach($CONTENT['Cookie'] as $k=>$v){ $HEADs['Cookie'].=(string)$k.'='.urlencode($v).'; '; }
$HEADs['Cookie']=substr($HEADs['Cookie'],0,-2);
}
if(isset($CONTENT)) if(isset($CONTENT['Authorization'])) if(is_array($CONTENT['Authorization'])){
if(isset($CONTENT['Authorization']['userid']) && isset($CONTENT['Authorization']['password']))
$HEADs['Authorization'] = 'Basic '.base64_encode(str_replace(':', '', $CONTENT['Authorization']['userid']).':'.$CONTENT['Authorization']['password']);
}
}
if(isset($HEADs['Content-MD5'])) if($HEADs['Content-MD5']===true) unset($HEADs['Content-MD5']);
if(!in_array(@$HEADs['Method'],array('GET', 'POST', 'PUT', 'OPTIONS', 'HEAD', 'DELETE', 'PATCH', 'TRACE', 'LINK', 'UNLINK')))$HEADs['Method']='GET';
$Send=$HEADs['Method'].' '.$HEADs['URI'].' '.$HEADs['HTTP'];unset($HEADs['Method'], $HEADs['URI'], $HEADs['HTTP']);
$keys=array_keys($HEADs);$lim=count($keys);
for($i=0;$i<$lim;$i++){
$Head=$keys[$i];
$Value=$HEADs[$Head];
$Send.="\r\n$Head: $Value";
}
$Send.="\r\n\r\n".$Content;
if(false!=($f=@fsockopen($SOCKETs['Socket-Address'], $SOCKETs['Socket-Port'], $errno, $errstr, $SOCKETs['Socket-Timeout']))){
if(!isset($SOCKETs['Socket-DownLimit'])) $ByteLimit=-1;
elseif (intval($SOCKETs['Socket-DownLimit'])>=0) $ByteLimit=intval($SOCKETs['Socket-DownLimit']);
else $ByteLimit=-1;
fputs ($f, $Send);
$Str='';
if($ByteLimit>0){
$Downed=0;
set_time_limit(5);
while(!feof($f) && $Downed<$ByteLimit){
$Str.=fread($f, $ByteLimit-$Downed);
$Downed=strlen($Str);
}
}elseif($ByteLimit<0){ while(!feof($f)){ $Str.=fgets($f, 512); } }
fclose($f);
}else return array(false, $errstr, $Send);
return array(true, $Str, $Send);
}
Вот функция, её добавить в ниже указанный код
roxblnfk
22.05.2010, 00:17
Код скрипта, отправляющего файл: (форум может поставить пробелы где не надо, но я старался делить длинные строки)
<?
/* Ф У Н К Ц И Ю В С Т А В И Т Ь С Ю Д А
ОПИСАНИЕ:::::::ФУНКЦИИ
Возвращает array ($Connected{true,false}, $Str{string}, $Send{string}(отправленный запрос))
Если $Connected==true, то $Str - ответ сервера, иначе $Str - текст ошибки сокета
В функцию передаются 3 массива
$SOCKET доолжен содержать значения:
'Socket-Address'=> адрес сервера (ip или домен)
'Socket-Port'=> удалённый порт (обычно 80)
'Socket-Timeout'=> максимальное время ожидания соединения
'Socket-DownLimit'=>ограничение на длину ответа (Байт). null - без ограничения, функция закачает и выдаст полный ответ сервера
$HEAD
Смотрите описание заголовков в функции
Все неуказанные заголовки либо берутся автоматически (важные), либо игнорируются (второстепенные)
$CONTENT
Указывайте тут POST данные, куки, логины и пароли для доступа
'Cookie'=>array('name'=>'ROX','session'=>'asagjreht89pqypgr7w5e4p',...) // передавайте в ассоциативном массиве Имя=>Значение
'POST'=>array(),
// Пост запрос можно организовать двумя способами:
1. Если нужно послать текстовые переменные, заполняйте массив как в случает с COOKIE (значения подвергаются urlencode)
2. Если нужно передать файлы и тексты, воспользуйтесь передачей множественного содержимого (см. MIME)
В этом случае массив примет вид:
$CONTENT['POST']=array(
array(
'name'=>'Это имя переменной (формы)', // если не указано, то берётся ключ этого суб-массива (0)
// 'name' соответствует атрибуту name в HTML-тегах <INPUT> и <TEXTAREA>
'filename'=>'image.jpg', // Если передаете файл, укажите имя файла
'Content-Type'=>'image/jpeg', // при передаче файла укажите формат файла
'Content-Transfer-Encoding'=>'binari', // бинарный файл, содержимое не закодировано
''=>'Собственно, само содержимое. Практически тут может быть всё что угодно', // не подвергается кодированию // ключ элемента - пустая строка
),
array(
''=>'текст' // здесь name=>1
),
'ololo'=>array(
''=>'тело объекта' // здесь name=>'ololo'
)
);
Заголовок каждого содержимого постоянен =>>> Content-Disposition: form-data
'Authorization'=>array(Login, Password), // Авторизация на сайте
1 Базовая схема установления подлинности (Basic Authentication Scheme)
'Authorization'=>array(
'userid'=>'User' // идентификатор клиента
'password'=>'123' // пароль
)
[x] 2 Обзорная схема установления подлинности (Digest Authentication Scheme); Обзорное установление подлинности для HTTP определяется в RFC 2069 [32] 2617 oO. // НЕ РЕАЛИЗОВАНО
[x] 'Proxy-Authorization'=>array(Login, Password), // Авторизация на HTTP прокси // НЕ РЕАЛИЗОВАНО
*/
$File='./de_baghdad2.rar';
$SizeLimit=512*1024;//500KB
$ReSend=5;
$SOCKET=array('Socket-Address'=>'127.0.0.1', 'Socket-Port'=>80, 'Socket-Timeout'=>10, 'Socket-DownLimit'=>null);
$CONTENT=array( 'Authorization' => array('userid'=>'User', 'password'=>'123'));
$HEAD=array(
'URI'=>'/get_file.php',
'Connection'=>false,
'Host'=>true,
'Content-Length'=>true, // Размер содержимого сущности в байтах. // если передаётся в $CONTENT, то будет заполнено автоматически, лучше не трогать
'Content-MD5'=>true, // MD5-хэш сущности для проверки целостности. // для автоматического заполнения перевести в ture
);
if(is_file($File))if(is_readable($File)){
$Size=filesize($File);
$For=ceil($Size/$SizeLimit);
if($For>0) if(false!==($FP=fopen($File,'r'))){
flock($FP,LOCK_SH);
$Sendet=0;
$MD5File=md5_file($File);
for($i=0; $i<$For; $i++){
fseek($FP, ($i*$SizeLimit) ,SEEK_SET);
$Segment=fread($FP, $SizeLimit);
$CONTENT['POST']=array(
array(
'name'=>'md5file',
''=>$MD5File
),
array(
'name'=>'fullsize',
''=>$Size
),
array(
'name'=>'start',
''=>($i*$SizeLimit)
),
array(
'name'=>'end',
''=>min(($i*$SizeLimit+$SizeLimit),$Size)
),
array(
'name'=>'md5segment',
''=>md5($Segment)
),
array(
'name'=>'filename',
''=>substr(strrchr(str_replace("\\",'/',$File),'/'),1)
),
array(
'name'=>'segmentname',
''=>'segment'
),
array(
'name'=>'segment',
'filename'=>'segment',
'Content-Transfer-Encoding'=>'binari',
''=>$Segment
)
);
$Sendet=false;
$j=0;
while(!$Sendet && $j<$ReSend){
$j++;
$Result=pro_HTTP_($SOCKET, $HEAD, $CONTENT);
$Sendet=$Result[0];
$Text=$Result[1];
}
if(!$Sendet){echo 'Файл не удалось отправить. Возникла ошибка на '.$i.' сегменте: '.$Text; break;}
echo strval($i+1)."-й пошёл!\r\n";
echo $Result[1]."\r\n\r\n<br>\r\n\r\n";
//echo strlen($Segment);
//print_r($CONTENT);
}
flock($FP,LOCK_UN);
fclose($FP);
}else echo 'Не удалось открыть файл';
else echo 'Файл нулевого размера.';
}
?>
roxblnfk
22.05.2010, 00:18
зы: функция pro_HTTP_() ещё не доделана, но в заданном условии работает как надо. Надо ещё сделать прокси и Digest (который всё-равно не сделаю, намудрили в спецификации, да и апач не поддерживает полностью)
Скрипт, принимающий файл: (там попутно указаны некоторые опции типа логина и пароля, имени файла... лучше изучить)
<?
$MessageA = 'Authorise, please';
$MessageB = 'Bad password or login';
function q_auth($Inp){
header('WWW-Authenticate: Basic realm="'.$Inp.'"');
header('HTTP/1.0 401 Unauthorized');
}
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])){
q_auth($MessageA);
}else{
$User=(string)$_SERVER['PHP_AUTH_USER'];
$Password=(string)$_SERVER['PHP_AUTH_PW'];
// контроль передачи данных для отладки
// ob_start();
// print_r($_FILES);
// print_r($_POST);
// $To=ob_get_contents();
// ob_end_flush ();
// $fp = fopen ('./sending file oO.txt','a');
// flock ($fp,LOCK_EX);
// fputs($fp,$To);
// flock ($fp,LOCK_UN);
// fclose($fp);
if($User!=='User' || $Password!=='123'){
q_auth($MessageB);
}else{
// Сохраняем по кускам файл
echo "ПОГНАЛИ!\r\n";
if(isset($_POST['md5file']) && isset($_POST['start']) && isset($_POST['end']) && isset($_POST['fullsize'])
&& isset($_POST['md5segment']) && isset($_POST['filename']) && isset($_POST['segmentname'])){
$SegmentName=$_POST['segmentname'];
$Start=intval($_POST['start']);
$End=intval($_POST['end']);
$Size=$End-$Start;
$FullSize=$_POST['fullsize'];
$md5file=$_POST['md5file'];
$md5segment=$_POST['md5segment'];
echo "ПОСТ ПРИШЁЛ! Size=$Size\r\n";
if($Size>0){
echo "РАЗМЕРЧИК НЕ ДЕРЬМО!\r\n";
if(isset($_FILES[$SegmentName])){
echo "СЕГМЕНТ ДЕТЕКТЕД!\r\n";
if($_FILES[$SegmentName]['size']==$Size && md5_file ($_FILES[$SegmentName]['tmp_name']) === strtolower($md5segment)){
//$CustomFileName=$_POST['filename'];// ненадёжно, нужны фильтры и проверки
$CustomFileName='./NotFileName.rar';
$fp = fopen ($CustomFileName,'a+');
flock($fp,LOCK_EX);
fseek($fp, $Start, SEEK_SET);
fputs($fp, file_get_contents ($_FILES[$SegmentName]['tmp_name']));
flock($fp,LOCK_UN);
fclose($fp);
if($End==$FullSize) if(md5_file($CustomFileName) === strtolower($md5file)) echo 'ФАЙЛ ЗАПИСАН КАК НАДО И ПОЛНОСТЬЮ! УРА! xD';
else echo 'ПИПЕЦ!';
else echo 'СЕГМЕНТ ЗАПИСАН!';
}else echo "НАЕ*А! size=".($_FILES[$SegmentName]['size'])."? если да, то md5 не тот\r\n";
}else echo 'А ФАЙЛ ТО ЗАБЫЛ ПЕРЕДАТЬ?';
}else echo 'ПОПУТАЛ РАЗМЕРЧИК! ';
}else echo 'ПОСТ ПЕРЕДАН НЕ ВЕСЬ!';
}
}
?>
В ходе теста файл отлично передался, вот мой результат
1-й пошёл!
HTTP/1.1 200 OK
Date: Fri, 21 May 2010 19:59:48 GMT
Server: Apache/2.2.14 (Win32) PHP/5.3.1
X-Powered-By: PHP/5.3.1
Content-Length: 77
Connection: close
Content-Type: text/html
ПОГНАЛИ!
ПОСТ ПРИШЁЛ! Size=524288
РАЗМЕРЧИК НЕ ДЕРЬМО!
СЕГМЕНТ ДЕТЕКТЕД!
<br>
2-й пошёл!
HTTP/1.1 200 OK
Date: Fri, 21 May 2010 19:59:48 GMT
Server: Apache/2.2.14 (Win32) PHP/5.3.1
X-Powered-By: PHP/5.3.1
Content-Length: 77
Connection: close
Content-Type: text/html
ПОГНАЛИ!
ПОСТ ПРИШЁЛ! Size=524288
РАЗМЕРЧИК НЕ ДЕРЬМО!
СЕГМЕНТ ДЕТЕКТЕД!
<br>
3-й пошёл!
HTTP/1.1 200 OK
Date: Fri, 21 May 2010 19:59:48 GMT
Server: Apache/2.2.14 (Win32) PHP/5.3.1
X-Powered-By: PHP/5.3.1
Content-Length: 119
Connection: close
Content-Type: text/html
ПОГНАЛИ!
ПОСТ ПРИШЁЛ! Size=459218
РАЗМЕРЧИК НЕ ДЕРЬМО!
СЕГМЕНТ ДЕТЕКТЕД!
ФАЙЛ ЗАПИСАН КАК НАДО И ПОЛНОСТЬЮ! УРА! xD
<br>
жаль за работу денег на платят :(
roxblnfk
23.05.2010, 23:24
ТС уже забил на тему? :(
^_WhitE_DeMoN_^
24.05.2010, 01:05
ТС уже забил на тему? :(
Да не, просто времени нету тестить - работы пох...
Скоро активизируюсь.
echo tpl_l() - выводит результат в теплейте (оформлен)
^_WhitE_DeMoN_^
24.05.2010, 01:18
ты думаешь, что админы дурачки и отключив сокеты и урл_фопен оставили работать курл? ну-ну
Очевидно дурачки :D
Еще не тестил, но из форума хоста понел что курл наш :)
^_WhitE_DeMoN_^
24.05.2010, 01:50
HTTP_request() вернёт МАССИВ, где первый элемент с ключем 0 будет true или false, второй элемент с индексом 1 — текст ошибки (в случае, если первый false) или ответ сервера (если первый элемент - true, т.е. коннект удался)
присвой значение переменной и бери условие...
$Result=HTTP_request();
if($Result[0]){
echo "запрос отправил, вот ответ:\r\n".$Result[1];
}else{
echo "Не удалось соедениться с сервером, вот текст ошибки:\r\n".$Result[1];
}
Такой вот фрагмент - не выводит ничего ! :confused:
$timeout=30; // таймаут соединения
$post=array('b' => $this->filename); // массив с переменными в формате ($var1 => $value1, $var2 => $value2...) {в $var# желательно использовать только латину}
$cookie=array();// cookies заполняется аналогично $post
$rezult = HTTP_request($serv, $port, $timeout, $host, $addr, $post, $cookie);
echo tpl_l($rezult[0].' --- '.$rezult[1], C_RESULT);
if($rezult[0]){
echo tpl_l("запрос отправил, вот ответ:\r\n".$rezult[1], C_RESULT);
}else{
echo tpl_l("Не удалось соедениться с сервером, вот текст ошибки:\r\n".$rezult[1], C_RESULT);
roxblnfk
24.05.2010, 10:42
Такой вот фрагмент - не выводит ничего ! :confused:
$timeout=30; // таймаут соединения
$post=array('b' => $this->filename); // массив с переменными в формате ($var1 => $value1, $var2 => $value2...) {в $var# желательно использовать только латину}
$cookie=array();// cookies заполняется аналогично $post
$rezult = HTTP_request($serv, $port, $timeout, $host, $addr, $post, $cookie);
echo tpl_l($rezult[0].' --- '.$rezult[1], C_RESULT);
if($rezult[0]){
echo tpl_l("запрос отправил, вот ответ:\r\n".$rezult[1], C_RESULT);
}else{
echo tpl_l("Не удалось соедениться с сервером, вот текст ошибки:\r\n".$rezult[1], C_RESULT);
если убрать твой tpl_l то всё нормально выводит :) (либо текст ошибки, либо контент страницы)
а вобще, в трёх своих предыдущих постах текущей темы я всю твою задачу решил... (там уже другая функция)
^_WhitE_DeMoN_^
25.05.2010, 01:32
если убрать твой tpl_l то всё нормально выводит :) (либо текст ошибки, либо контент страницы)
а вобще, в трёх своих предыдущих постах текущей темы я всю твою задачу решил... (там уже другая функция)
Логики нет. Посмотрим...
Но я никуда не спешу (уже...), все протестирую (что как заработает) и репу колотить буду, спасиб ;)
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot