通过常量连接的PHP SFTP命令

时间:2013-10-24 02:34:19

标签: php html ftp sftp phpseclib

我正在开发一个网站,作为家用机器的在线SFTP客户端。到目前为止,我所拥有的解决方案是一个索引(主要)php文件,它包含站点的UI,以及一个与phpseclib(SFTP连接管理器)连接的SFTP PHP便利类。

index.php

<?php
require_once "php/Membership.php";
require_once "php/ssh.php";
require_once "php/sftp.php";

$sftp = new SFTP();

error_reporting(E_ALL);  // will report any errors your code may have
ini_set("display_errors", 1);

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!ATTLIST td fileName CDATA #IMPLIED>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SFTP</title>
<link href="index.css" rel="stylesheet" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="index.js"></script>
</head>

<body>
<h1 id="welcome">Welcome</h1>

<div id="container">
<div id="content">

<!--SFTP Files-->
<div style="height:1000px; overflow:auto;">
<?php $sftp->set_table(NULL, NULL);?>
</div>


</div>
</div>
</body>
</html>

SFTP.php

<?php

include('Net/SFTP.php');

class SFTP {

    private $sftp;

    function __construct() {

     $this->sftp = new Net_SFTP('99.99.9999.999');
     if (!$this->sftp->login('user', 'pwd')) {
         exit('Login Failed');
     }
        echo $this->sftp->pwd() . "\r\n";
    }

    function set_table($table, $directory) {
        if (isset($directory)) {
            $this->sftp->chdir($directory);
        }
        echo '<table id="sftpTable" style="border:1px solid;">';
        $result = $this->sftp->nlist();
        foreach ($result as $row) {
            if (substr($row, 0, 1) != '.') {
                echo "<tr>" . "<td class='columnSelect' id=" . $row . "><form method='post' action=''>" . $row . "<input type=\"hidden\" name=\"index\" value=\"" . $row . "\" /></form></td>";
                if (strpos($row,'.') !== false)
                    echo '<td>'. $this->parseBytes($this->sftp->_size($row)) . '</td></tr>';
            }   
        }
        echo '</table>';
    }

    function parseBytes($bytes) {
        if ($bytes / 1074000000 >= 1) {
            return $bytes / 1074000000 . 'GB';
        }
        if ($bytes / 1048576 >= 1) {
            return $bytes / 1048576 . 'MB';
        }
        if ($bytes / 1024 >= 1) {
            return $bytes / 1024 . 'KB';
        }
        return $bytes . 'B'; 
    }
}

?>

现在我遇到的问题似乎是循环逻辑。我最初的想法是建立一个以下列方式运作的系统:

  1. 建立与SFTP的单一连接
  2. 对该单身人士进行查询
  3. 在UI中显示结果
  4. 我计划显示一个表格,其中可点击的行代表服务器上目录中的不同项目。当用户点击其中一行时,我希望系统返回那个目录的新项目列表,并相应地更新UI。为了实现这一点,我尝试在每个表行中添加一个隐藏字段,以保存该单元格的列表名称。单击单元格后,我需要提取该隐藏字段的值并使用新目录重置该表。然后出现了更换屏幕上的表格而不仅仅是回应新表格的问题。

    因此,我的问题是:

    以这种方式存储与每个单元格相关的目录的最佳方法是,单击该单元格时,SFTP单例会根据新目录重置一个表吗?

    请注意,上述代码可能存在逻辑错误,这可能对新查看者没有多大意义,因为已经进行了许多不同的尝试。另外,要明确的是,我正在寻找正确方向的方法论观点,而不是为我编写代码的人。

    提前致谢。

1 个答案:

答案 0 :(得分:1)

In PHP, the singleton paradigm is considered "bad practice".请参阅参考:Best practice on PHP singleton classes

虽然您的SFTP类似乎没有在上面的示例中实际实现单例逻辑。

您的下一个挑战是,当您按原样呼叫网页时,将重新加载整个网页。通过某种服务器端缓存,您当前的架构中无法仅更新页面的一部分。正如评论中所提到的,AJAX将成为您选择的工具。

单身人士根本不存在PHP浏览器对Web服务器的调用。每次浏览器访问Web服务器时,都必须创建新的SFTP连接。每次Web服务器完成请求时,它都会破坏它正在使用的SFTP连接。

您正在寻找的方法指针:

  1. 有一个页面加载初始UI(让我们称之为视图),在 浏览器。您可能需要提供一些基本配置 至少,您可能只是在第一次通话时加载100%。
  2. 开发一些仅提供数据的其他页面,最好是在 json格式。
  3. 在视图中有javascript(ajax) 离散调用服务器返回数据(您的表)。
  4. 当你点击页面时,ajax会对apropo进行离散调用 正确的页面,以提供正确的数据,然后刷新/更新 用户界面中的正确元素。
  5. 我个人是Memcached的粉丝,用于缓存服务器请求之间的会话数据。话虽这么说,有大量的缓存服务可用于在Web服务器上保存目录列表,直到需要从SFTP服务器刷新。

    在为您的挑战研究最佳缓存解决方案时,确保您了解操作码缓存之间的区别是值得的(有许多操作码缓存可供使用。您有APCXCacheeAcceleratorZend Platform。)和数据缓存(会话,变量,用户空间 - 我们建议使用memcached)。

    但是,如果您的数据足够大(> 1MB),您通常不希望将其缓存在memcached之类的任何内容中,您可能希望将其缓存到本地文件系统,这是我最近如何做的一个示例这是一个非常大的阵列。

    /**
     * Will serialize, then write the array to disk, returning the filePath
     * 
     * @param array $array
     * @param string $filePath
     * @return string
     */
    function putCacheData(array $array, $filePath = NULL){
        if (empty($filePath)){
            $filePath = tempnam(NULL, 'IMPORT');
        }
        $serializedData = serialize($array);
        file_put_contents($filePath, $serializedData);
        return $filePath;
    }
    
    /**
     * Reads the file, unserializes the data, and returns the array.
     * 
     * @param string $filePath
     * @return Array|FALSE
     */
    function getCacheData($filePath){
        $array = array();
        if (empty($filePath)){
            logmessage("The filepath: [$filepath] is empty!");
            return $array;
        }
    
        if (! is_file($filePath)){
            putImportData($array, $filePath);
            return $array;
        }
    
        return unserialize( file_get_contents( $filePath ) );   
    }
    

    然后我们只将$filePath存储在用户会话数据中(这将转发给我们的memcached),当我引导每个请求时,我可以检查会话中的路径,加载缓存的数据,确定是否存在是否已过期,并可选择刷新它。只需确保在活动请求结束之前将数据写入文件。