5

我想使用 PHP 读取远程文本文件(最好使用 fopen)。当我在本地文件上使用此函数时,我的脚本使用 fopen 工作。

我试过了:

$file = fopen ("http://abc.abc.abc", "r");
if (!$file) {
    echo "<p>Unable to open remote file.\n";
    exit;
}

我得到了:

警告:fopen(http://abc.abc.abc):打开流失败:由于目标机器主动拒绝,无法建立连接。在第 2 行的 C:\xampp\htdocs\NMR\nmrTest5.php 中无法打开远程文件。

我读过phpseclib可能是一个不错的选择,因为我可以使用 WinSCP (SFTP) 或使用 Puttyfor 访问我的文件,所以我尝试了这个(在将所有文件从 phpseclib 复制到我的目录之后)希望我可以在本地复制文件,然后用 fopen 读取它(这不是遇到的最好的事情,但我可以忍受):

include('Net/SFTP.php');

$sftp = new Net_SFTP('abc.abc.abc');
if (!$sftp->login('username', 'pass')) {
    exit('Login Failed');
} 

我得到了:

注意:在第 1561 行的 C:\xampp\htdocs\NMR\Net\SSH2.php 中找不到兼容的服务器到客户端加密算法 Login Failed

有趣的是,如果我连接到服务器(使用 WinSCP),我会收到不同的消息:

注意:从第 3362 行 C:\xampp\htdocs\NMR\Net\SSH2.php 中的套接字读取错误

注意:C:\xampp\htdocs\NMR\Net\SSH2.php 中的服务器在第 1471 行关闭连接登录失败

关于如何让它工作的任何想法?理想情况下,我会使用 fopen,但我愿意接受其他解决方案。

4

3 回答 3

2

我自己刚刚解决了这个确切的问题,在任何一个地方都找不到任何好的文档来说明如何完成这个问题。

我刚刚制作了一个使用 Monolog 的日志服务,并且基本上根据正在写入/创建的日志文件制作了一个自定义流处理程序。因此,它需要一种资源(例如由 创建的资源fopen)才能将日志文件写入 SFTP 服务器。

我让它像这样使用 ssh2 库工作:

$connection = ssh2_connect($this->host, 22);
ssh2_auth_password($connection, $this->user, $this->password);

$sftp = ssh2_sftp($connection);

//some stuff to do with whether the file already exists or not

$fh=fopen("ssh2.sftp://$sftp".ssh2_sftp_realpath($sftp,".")."/$this->logName/$this->fileName", 'a+');

return new StreamHandler($fh);

一切都运行良好,直到我将该服务集成到另一个项目中并意识到这仅适用于我的开发机器,因为它已按照此问题中的概述libssh2安装了库。

不幸的是,生产服务器并不那么容易添加库。因此,我发现自己正在寻找不同的解决方案。

我在其他项目中使用过,phpseclib但仅用于基本和一些电话。get()put()nlist()

为了让这个工作我不得不使用一个Stream对象。没有很好的记录,但这里有一个很好的讨论

根据那里的信息,再加上在SFTP课堂上的一些挖掘,特别是get()功能,这就是我设法实现相同功能的方式phpseclib

SFTP\Stream::register();
$sftpFileSystem = new SFTP($this->host);
if (!$sftpFileSystem->login($this->user, $this->password)) {
    throw new Exception("Error logging in to central logging system. Please check the local logs and email for details", 1);
}

$context = [
    'sftp' => [
        'sftp' => $sftpFileSystem
    ],
];

//some stuff to do with whether the file already exists or not
$remote_file = $sftpFileSystem->realpath('test.txt');

$sftpStream = fopen("sftp://.{$remote_file}", 'a+', null, stream_context_create($context));
if (!$sftpStream) {
    exit(1);
}

return new StreamHandler($sftpStream);

请注意调用. 后的点 ( .) 。浪费了我半个小时!sftp://fopen()

于 2019-01-04T17:05:09.377 回答
2

这就是我使用 phpseclib 解决问题的方式,正如@neubert 在我的问题评论中所建议的那样。

我首先在我的服务器上添加了phpseclib文件夹。然后我在我的 PHP 文件中使用了这段代码来访问我在远程服务器上的文件:

//needed for phpseclib
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include_once('Net/SFTP.php');

//connection to the server
$sftp = new Net_SFTP('abc.abc.abc');
if (!$sftp->login('my_login', 'my_password')) {
  exit('Login Failed');
}

//dump entire file in a string, convert to an array and check number of lines

else {
  $text = $sftp->get('full_path_to_my_file');
}
$myArray = explode("\n", $text);
$nbline = count($myArray);
于 2019-01-06T16:23:39.973 回答
1

我遇到了与 fopen 类似的问题。卷曲可用于这些目的。

请检查以下基本示例函数(如果 url 是 https,请取消注释 CURLOPT_SSL_VERIFYPEER = FALSE 行)。

$url = '***THE URL***';
$result = get_web_page_by_curl($url);

if ($result['errno'] != 0) echo 'error: bad url, timeout, redirect loop ...';
if ($result['http_code'] != 200) echo 'error: no page, no permissions, no service ...';
else {
    $page = $result['content'];
    echo $page;
}

function get_web_page_by_curl($url) {
    $agent = "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)";

    $options = array(
        CURLOPT_RETURNTRANSFER => true,     // return web page
        CURLOPT_HEADER         => false,    // don't return headers
        CURLOPT_FOLLOWLOCATION => true,     // follow redirects
        CURLOPT_ENCODING       => "",       // handle all encodings
        CURLOPT_USERAGENT      => $agent,   // who am i
        CURLOPT_AUTOREFERER    => true,     // set referer on redirect
        CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
        CURLOPT_TIMEOUT        => 120,      // timeout on response
        CURLOPT_MAXREDIRS      => 10,       // stop after 10 redirects
        //CURLOPT_SSL_VERIFYPEER => FALSE   // this line makes it work under https 
    );

    $ch = curl_init($url);
    curl_setopt_array($ch, $options);
    $content = curl_exec($ch);
    $err     = curl_errno($ch);
    $errmsg  = curl_error($ch);
    $header  = curl_getinfo($ch);
    curl_close($ch);

    $header['errno']   = $err;
    $header['errmsg']  = $errmsg;
    $header['content'] = $content;
    return $header;
}
于 2018-07-29T19:22:26.133 回答