Can';不要让SFTP在PHP中工作
我正在用PHP编写一个简单的SFTP客户端,因为我们需要通过n个远程服务器以编程方式检索文件。我正在使用PECL SSH2扩展 不过,我遇到了一个路障。php.net上的文档建议您可以这样做:Can';不要让SFTP在PHP中工作,php,ssh,wrapper,sftp,Php,Ssh,Wrapper,Sftp,我正在用PHP编写一个简单的SFTP客户端,因为我们需要通过n个远程服务器以编程方式检索文件。我正在使用PECL SSH2扩展 不过,我遇到了一个路障。php.net上的文档建议您可以这样做: $stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r'); 但是,我有一个ls方法,它试图实现类似的功能 public function ls($dir) { $rd = "ssh2.sftp://{$this->sftp}/$dir";
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');
但是,我有一个ls方法,它试图实现类似的功能
public function ls($dir)
{
$rd = "ssh2.sftp://{$this->sftp}/$dir";
$handle = opendir($rd);
if (!is_resource($handle)) {
throw new SFTPException("Could not open directory.");
}
while (false !== ($file = readdir($handle))) {
if (substr($file, 0, 1) != '.'){
print $file . "\n";
}
}
closedir($handle);
}
我得到以下错误:
PHP Warning: opendir(): Unable to open ssh2.sftp://Resource id #5/outgoing on remote host
这非常有意义,因为当您将资源强制转换为字符串时会发生这种情况。文档是否有误?我尝试用主机、用户名和主机替换资源,但也没有成功。我知道路径是正确的,因为我可以从命令行运行SFTP,它工作得很好
是否有其他人尝试将SSH2扩展与SFTP一起使用?我是不是漏掉了什么明显的东西
更新:
我在内部的另一台机器上设置了sftp,它工作得很好。因此,我试图连接的服务器一定有什么地方不工作。我也遇到了类似的问题。我假设您正在做类似的事情:
$dir = "ssh2.sftp://{$sftp}{$remote_dir}";
$handle = opendir($dir);
当$remote\u dir
是根目录的完整路径时,open\u dir
起作用。如果$remote\u dir
只是“/”或“”,那么我会像您一样出现“无法打开”错误
在我的例子中,ssh似乎是在根文件夹而不是像ftp那样在“home”目录下连接的。您提到它在不同的服务器上工作,所以我想知道这是否只是一个配置问题。我最近尝试让PHP上的SFTP工作,发现phpseclib更易于使用:
如果您有幸不在共享主机上,并且可以安装任何您想要的扩展,那么PECL扩展可能会更好,但并非所有人都这么幸运。另外,phpseclib的API看起来更直观,是面向对象的。我也遇到了同样的问题,但我可以解决这个问题 在我的情况下,当连接到服务器时,我将转到帐户的根目录,由于服务器配置,我无法在那里写入 我已经使用fireFTP连接到该帐户,因此我可以看到该帐户的根在哪里…它是服务器的根 我必须包括整个路径,直到允许我写入的文件夹,这样我才能解决这个问题 因此,我的建议是使用图形界面获取路径(我使用了fireFTP),并将整个路径添加到代码中
$pathFromAccountRootFolderToMyDestinationFolder = '/Account/Root/Folder/To/My/Folder';
$stream = fopen("ssh2.sftp://".$sftp."/".$pathFromAccountRootFolderToMyDestinationFolder."/myFile.ext", 'r');
希望这将有助于你和其他人与同样的问题
干杯 让SFTP在PHP内(甚至在windows上)工作而不安装任何扩展等最简单的方法是PHPSECLIB:。SSH内容完全在PHP类中实现 您使用的是这样的:
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
echo $sftp->pwd();
?>
$rd = "ssh2.sftp://{$this->sftp}/./";
该页上的文档包含错误。请看下面的示例:-您实际需要做的是在将其与fopen()一起使用之前,使用ssh2_SFTP()打开一个特殊的SFTP资源。是的,它看起来就像那样,例如,当转换为字符串时,“Resource#24”。。。有点奇怪,但很明显它是有效的
另一个警告是,SFTP在根目录而不是远程用户的主目录中启动,因此URI中的远程路径应该始终是绝对路径。当连接到SFTP服务器时,您需要连接到根文件夹(例如,读取文件夹的内容)仅使用“/”作为路径时,仍然会出现错误 我找到的解决方案是使用路径“/。/”,这是引用根文件夹的有效路径。当您登录的用户只能访问其自己的根文件夹,并且没有可用的完整路径时,这非常有用 因此,当尝试读取根文件夹的内容时,对服务器的请求应该如下所示:
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
echo $sftp->pwd();
?>
$rd = "ssh2.sftp://{$this->sftp}/./";
我的问题是,我在函数中连接并返回包含资源的字符串URL。不幸的是,资源不是在函数上下文中创建的,垃圾收集器正在断开函数端的资源连接。解决方案:通过引用返回资源,并在更复杂的上下文中手动取消设置它。对于php版本>5.6.27,请使用intval()
通过在(Powershell)服务器上启用sftp支持解决了我的问题这是多年前我在ssh2包中发现的一个错误,并在php.net上发布了一个补丁。它修复了此问题,但需要重建ssh2 pecl包。您可以在此处阅读更多:。我在包中的ssh2_fopen_wrappers.c文件中添加了一个补丁来修复这个问题。以下是我的评论: 下面是ssh2_fopen_wrappers.c中导致此错误的一行代码:(包括注释) 这一行代码——也就是这个bug——是作为bug#59794的修复而引入的。这行代码试图从path变量中获取包含部件、查询和片段的字符串。 考虑路径变量的这个值:
ssh2.sftp://Resource id #5/topdir?a=something#heading1
当resource->path为“/topdir”时,结果是“/topdir?a=something#heading1”被分配给resource->path,就像注释所说的那样
现在考虑资源->路径为“/”时的情况。执行代码行后,resource->path变为“//resource id#5/topdir#heading1”。这显然不是你想要的。下面是一行代码,用于:
resource->path = estrdup( strstr( strstr( path, "//" ) + 2, "/" ) );
在调用php_url_parse()之前,您可能还需要应用bug#73597的修补程序,该修补程序会从路径字符串中删除“Resource id”。您能确认ssh2连接正在工作吗?使用任何其他ssh2函数如何?ssh2\u connect()ssh2\u auth\u password()ssh2\u sftp()都工作正常。据我所知,我有一个有效的连接资源。从我所看到的,你是对的。它连接到根目录而不是“home”。使用命令行sftp客户端确实连接到“home”。我可能只需要从尝试连接到的客户端获取绝对路径。
$dir='ssh2.sftp://'.$sftp.//'.$absolute\u path代码>使用绝对值