PHP FTP使用套接字 - 每次登录只能下载一个文件?

时间:2014-11-18 12:26:13

标签: php sockets ftp

我已经将这个问题撞到了墙上几个小时。我正在编写一个FTP客户端来从远程FTP服务器检索文件(标准的php ftp工具只返回真或假响应 - 我需要错误代码和消息)。它仍在进行中,但我发现我可以正常下载单个文件,但当我尝试下载两个或更多PASV请求时,不会返回打开数据所需的IP地址和端口号连接。我真的很难理解为什么所以任何帮助都会非常感激。提前致谢! ç

这是代码......

include_once "FTP/socketFTP.php";

$host = "127.0.0.1";
$port = 21;

$username = "xxx";
$password = "yyy";

$ftpClient = new socketFTP();
if ($ftpClient) {
    $ftpClient->destinationFolder = 'c:\\users\\xxx.yyy\my-data\\';
    $status = $ftpClient->connect($host, $port);
    $status = $ftpClient->login($username, $password);
    $status = $ftpClient->chdir("/test-data/");
    //$status = $ftpClient->getFile('foo.txt');
    $entries = $ftpClient->dirList();

    $status = $ftpClient->retrieveAllFilesInDirectory();

    $ftpClient->close();

}

<?php

class socketFTP {

private $control;
private $host;
public $destinationFolder;

public function connect($host, $port = 21, $timeout = 90) {

    if (!is_string($host) || !is_integer($port) || !is_integer($timeout)) {
        throw new exception("Invalid host, port or timeout properties provided.");
    }

    //$addr = gethostbyname($host);
    $addr = $host;  
    $control = stream_socket_client("tcp://" . $addr . ":" . $port, $errno, $errorMessage);

    do {
        $content[] = fgets($control, 8192);
        $array     = socket_get_status($control);   
    } while ($array['unread_bytes']);

    $status = $this->retrieveResponse($content);

    if ($control === false) {
        throw new exception("Unable to connect to server: " . $host . " port: " . $port . ". Please check network and server status.");
    }

    $this->control = $control;
    $this->host = $host;

    return true;
}

public function login($username, $password) {

    fwrite($this->control, "USER " . $username . "\r\n");
    $content = array();
    do {
        $content[] = fgets($this->control, 8192);
        $array     = socket_get_status($this->control);
    } while ($array['unread_bytes'] > 0);

    fwrite($this->control, "PASS " . $password . "\r\n");
    do {
        $content[] = fgets($this->control, 8192);
        $array     = socket_get_status($this->control);
    } while ($array['unread_bytes'] > 0);

    // TODO - return status

    return true;
}

public function close() {
    fclose($this->control);
}


public function chdir($pwd)
{
    if (!is_string($pwd)) {
        return array('code' => '550', 'message' => 'CWD Failed. ' . $pwd . 'does not exist');
    }

    fwrite($this->control, "CWD " . $pwd . "\r\n");
    do {
        $content[] = fgets($this->control, 8192);
        $array     = socket_get_status($this->control);
    } while ($array['unread_bytes'] > 0);   

    return true;

}



public function getFile($filename) {

    $content = array();
    fwrite($this->control, 'PASV ' ."\r\n");    
    do {
        $content[] = fgets($this->control, 128);
        $array     = socket_get_status($this->control);
    } while ($array['unread_bytes']);

    $status = $this->retrieveResponse($content);    
    $dataPort = $this->getDataPortNumber($status['message']);

    if (is_numeric($dataPort) and $dataPort > 0) {
        $client = stream_socket_client("tcp://" . $this->host . ":" . $dataPort, $errno, $errorMessage);
        if ($client === false) {
            throw new UnexpectedValueException("Failed to connect: $errorMessage");
        }

        $content = array();
        fwrite($this->control, 'RETR ' . $filename ."\r\n");
        do {
            $content[] = fgets($this->control, 8192);
            $array     = socket_get_status($this->control);
        } while ($array['unread_bytes']);
        $this->retrieveResponse($content);

        $contents = stream_get_contents($client);
        fclose($client);

        $status = $this->saveFile($filename, $contents);

    } else {
        throw new UnexpectedValueException("Failed to connect - Invalid port number specified for a data connection in FTP->getFile()");
    }

    return $status;

}

public function dirList() {

    fputs($this->control, 'PASV' ."\r\n");
    do {
        $content[] = fgets($this->control, 8192);
        $array     = socket_get_status($this->control);
    } while ($array['unread_bytes']);

    $status = $this->retrieveResponse($content);

    $dataPort = $this->getDataPortNumber($status['message']);

    echo "Port: $dataPort<br />";

    $client = stream_socket_client("tcp://" . $this->host . ":" . $dataPort, $errno, $errorMessage);
    if ($client === false) {
        throw new UnexpectedValueException("Failed to connect: $errorMessage");
    }
    fputs($this->control, 'LIST' ."\r\n");
    do {
        $content[] = fgets($this->control, 8192);
        $array     = socket_get_status($this->control);
    } while ($array['unread_bytes']);
    $this->retrieveResponse($content);
    $contents = stream_get_contents($client);
    fclose($client);

    $entry = array();
    $files = explode("\n", trim($contents));

    foreach ($files as $file) {
        $fileData = preg_split("/\s+/", $file);
        $permissions = $fileData[0];
        if (substr($permissions, 0, 1) != 'd') {
            $entry[] = $fileData[8];
        }
    } 

    return $entry; // A list if filenames

}

public function retrieveAllFilesInDirectory() {

    $files = $this->dirList();

    foreach ($files as $file) {
        echo "Retrieving file: $file<br />";
        $this->getFile($file);

    }

}


public function getDataPortNumber($message) {

    $start = strpos($message,'(');
    $data = substr($message, $start);
    $data = preg_replace("/[().]/","",$data);
    $elements = split(',', $data);

    $port = $elements[4] * 256 + $elements[5];
    return $port;
}


function retrieveResponse($message) {
    $info = $message[0];
    $code = substr($info, 0, 3);
    $message = substr($info,3);
    echo $code . " => " . $message . "<br />";
    return array('code' => $code, 'message' => $message);
}


function saveFile($filename, $contents) {
    $f = $this->destinationFolder . $filename;
    echo "Filename : $f<br />";
    $status = file_put_contents($f, $contents);
}


function fwrite_with_retry($sock, &$data)
{
    $bytes_to_write = strlen($data);
    $bytes_written = 0;

    while ( $bytes_written < $bytes_to_write )
    {
        if ( $bytes_written == 0 ) {
            $rv = fwrite($sock, $data);
        } else {
            $rv = fwrite($sock, substr($data, $bytes_written));
        }

        if ( $rv === false || $rv == 0 )
            return( $bytes_written == 0 ? false : $bytes_written );

        $bytes_written += $rv;
    }

    return $bytes_written;
}   

}

我得到的回应是:

220 =&gt;欢迎...... 227 =&gt;进入被动模式(127,0,0,1,229,104) 港口:58728 227 =&gt;进入被动模式(127,0,0,1,229,104) 226 =&gt;转移确定

注意:未定义的偏移量:第180行的C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php中的4

注意:未定义的偏移量:在第180行的C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php中为5 端口:0

警告:stream_socket_client():无法在C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP中连接到tcp://127.0.0.1:0(请求的地址在其上下文中无效。)。第132行的PHP

致命错误:未捕获的异常&#39; UnexpectedValueException&#39;消息&#39;连接失败:请求的地址在其上下文中无效。 &#39;在C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php:134堆栈跟踪:#0 C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php(162):socketFTP-&gt; dirList( )#C:\ xampp \ htdocs \ socket-ftp \ socketGo.php(21):socketFTP-&gt; retrieveAllFilesInDirectory()#main {main}抛出C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP。第134行的PHP

0 个答案:

没有答案