Автоматичная закачка файла - альтернатива FTP ?

Discussion in 'PHP' started by ^_WhitE_DeMoN_^, 30 Apr 2010.

  1. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    Таак, написал 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
     
  2. LStr1ke

    LStr1ke Elder - Старейшина

    Joined:
    29 Jul 2009
    Messages:
    801
    Likes Received:
    145
    Reputations:
    73
    Ну например так:

    1 хост, который делает дамп:
    PHP:
    <?php
    /* 
    {
    Тут делаешь дамп и сораняешь файл локально
    }
    */

    $damp_file "db.sql"//Тут имя файл который сдампился
    echo file_get_contents("http://my_server_2/saver.php?file=".$damp_file); //Тут ты передаешь хосту №2 какой файл ему скачивать
    ?>
    Хост №2 который скачивает
    PHP:
    <?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()
    //практикуем убийство серверов?)))
     
    #2 LStr1ke, 30 Apr 2010
    Last edited by a moderator: 30 Apr 2010
    2 people like this.
  3. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    Ожидается что будет большой, и еще 50 штук таких... Базы phpBB3 =)
    Иначе все понятно, спасибо огромное, щас в репу стукну

    Няя, я не убиец =) Я наемный убиец =) ...а так, сайто строитель...
     
  4. Deathdreams

    Deathdreams Elder - Старейшина

    Joined:
    8 Nov 2008
    Messages:
    342
    Likes Received:
    116
    Reputations:
    5
    скрипт, который дампит (в переменной $server указать путь до скрипта, который скачивает):
    Code:
    <?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.';
    
    ?>
    скрипт для сохранения дампа:
    Code:
    <?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');
    
    
    ?>
    
    /*писалось на скорую руку, подправьте если что не так*/
     
  5. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    ^_WhitE_DeMoN_^ если блокируются только функции ftp_*, напишите свой класс на сокетах, благо FTP - простейший протокол

    Или еще проще:
    PHP:
    file_put_contents("ftp://user:[email protected]/file.txt"file_get_contents('имя_локального_файла'));
     
    _________________________
  6. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    Удивил, проще некуда! Но, пока сделал первый вариант... И хз че еще у хостера запрещенно ;)
     
  7. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    Хост ругается:
    Идеи :confused:
     
  8. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    У никого ?
     
  9. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    Нет доступа к php.ini
    Ищу обход...
     
  10. ghostwizard

    ghostwizard Member

    Joined:
    4 Dec 2005
    Messages:
    127
    Likes Received:
    36
    Reputations:
    21
    Обязательно ftp ?

    1. Пробуй через сокеты, если не запрещено.
    2. Напрямую через 80-й порт.
     
  11. LStr1ke

    LStr1ke Elder - Старейшина

    Joined:
    29 Jul 2009
    Messages:
    801
    Likes Received:
    145
    Reputations:
    73
    ini_set();
    или читай через сокет

    http://ru2.php.net/manual/en/function.fsockopen.php
     
  12. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    FTP - не обязательно.
    Нужно только реализовать закачку файла с одного сервера на другой, а как ето уже проблем... Со сокетами не знаком, но придется доки курить...

    ini_set('allow_url_fopen', 'On'); не помогло...
     
  13. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    И через сокеты не пашет - URL file-access is disabled in the server configuration (2)

    Другие идеи..?
     
  14. roxblnfk

    roxblnfk Elder - Старейшина

    Joined:
    6 Feb 2010
    Messages:
    189
    Likes Received:
    42
    Reputations:
    19
    слать через POST, если файлы большие (или ограничение на POST), то кусками с указанием сегментов :)

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

    Далее, получив согласие получателя и код сессии начинаем передавать сегменты файла:
    указать только начало, конец, контрольную сумму (на всякий) обрывка; сессию на файл
    Принимающий собирает по кускам, проверяет получившуюся контрольную сумму и всё.
    Ну и написать проверку, что если были ранее начаты сессии с незаконченными передачами, которые не обновлялись более часа, то их стоит удалить.

    куски файла можно зипировать..
    а если и в base64 закодировать, то можно и GET-ом передать xD правда там на заголовки больше уйдёт трафика, но система будет работать :D
     
    #14 roxblnfk, 17 May 2010
    Last edited: 17 May 2010
    1 person likes this.
  15. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    Вообще не врубил...
     
  16. LStr1ke

    LStr1ke Elder - Старейшина

    Joined:
    29 Jul 2009
    Messages:
    801
    Likes Received:
    145
    Reputations:
    73
    При base64 строка увеличиться в несколько раз, а метод GET при отправки большого количества данных какбе не лучший вариант.

    ^_WhitE_DeMoN_^, Ты сокетами, надеюсь, отправлял заголовки?
     
    2 people like this.
  17. roxblnfk

    roxblnfk Elder - Старейшина

    Joined:
    6 Feb 2010
    Messages:
    189
    Likes Received:
    42
    Reputations:
    19
    я об этом и говорю, что заголовки ппц будут :)


    ^_WhitE_DeMoN_^, написл для тебя функцию с коментами. Если не новиш в php, то дальше сам разрулишь
    (функцию можешь не изучать, просто используй как надо, хотя в ней многое не учтено, но для простых запросов хватит)

    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($f512);
            }
            
    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));
     
    #17 roxblnfk, 17 May 2010
    Last edited: 18 May 2010
    1 person likes this.
  18. |qbz|

    |qbz| Banned

    Joined:
    25 Dec 2009
    Messages:
    385
    Likes Received:
    169
    Reputations:
    65
    kuri htaccess
     
  19. ^_WhitE_DeMoN_^

    Joined:
    1 Mar 2009
    Messages:
    101
    Likes Received:
    10
    Reputations:
    0
    @LStr1ke, неа...

    @roxblnfk, возвращает "1" =(

    @|qbz|, и .htaccess не прокатил...
     
  20. roxblnfk

    roxblnfk Elder - Старейшина

    Joined:
    6 Feb 2010
    Messages:
    189
    Likes Received:
    42
    Reputations:
    19
    ^_WhitE_DeMoN_^, ошибка есть, тут: $str{4}="\n";
    надо $str{3}="\n";
    А где возвращает 1? :)

    я тут RFC протокола перечитал, увидел следующее на счёт Content-Length:
    Длина тела объекта (entity-body) - это длина тела сообщения (message-body), полученного после декодирования всех кодирований передачи.
    Т.е., как я понял, сюда надо вписывать не длину закодированного контента, а длину контента до кодирования. В нэте в примерах показывают обратное, т.е. указывают длину закодированного контента.
    Вобщем немного переделал функцию (тут длина до кодирования):

    PHP:
    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($f512);}
            
    fclose($f);
        }else return array(
    false$errstr);
        return array(
    true$ss); 
    }
    надеюсь в Content-Length учитываются разделители и названия переменных :)

    Кстати, чтобы передавать бинарные данные, лучше использовать MIME без всякого кодирования. Этим же способом передают фотки с текстом за 1 раз. С момента прошлого поста я успел написать функцию, реализующую MIME в POST, только не закончил. В функции нет возможности аутентификации (Digest Authentication), но эти заголовки несложно дописать вручную. Если надо, могу поделиться.
     
    #20 roxblnfk, 20 May 2010
    Last edited: 20 May 2010