PHP:读取远程文件(最好使用 fopen)
PHP: read a remote file (ideally using fopen)
我想使用 PHP 读取远程文本文件(最好使用 fopen)。当我在本地文件上使用此函数时,我的脚本使用 fopen 工作。
我试过:
$file = fopen ("http://abc.abc.abc", "r");
if (!$file) {
echo "<p>Unable to open remote file.\n";
exit;
}
我得到了:
Warning: fopen(http://abc.abc.abc): failed to open stream: No connection could be made because the target machine actively refused it. in C:\xampp\htdocs\NMR\nmrTest5.php on line 2 Unable to open remote file.
我读到 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');
}
我得到了:
Notice: No compatible server to client encryption algorithms found in C:\xampp\htdocs\NMR\Net\SSH2.php on line 1561
Login Failed
有趣的是,如果我连接到服务器(使用 WinSCP),我会收到不同的消息:
Notice: Error reading from socket in C:\xampp\htdocs\NMR\Net\SSH2.php on line 3362
Notice: Connection closed by server in C:\xampp\htdocs\NMR\Net\SSH2.php on line 1471
Login Failed
知道如何让它工作吗?理想情况下我会使用 fopen 但我愿意接受其他解决方案。
我遇到过与 fopen 类似的问题。
Curl 可用于这些目的。
请检查以下基本示例函数(如果 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;
}
我自己一直在解决这个确切的问题,但在任何一个地方都找不到任何关于如何完成这个问题的好文档。
我刚刚制作了一个使用 Monolog 的日志记录服务,并且基本上根据正在写入的日志文件制作了一个自定义流处理程序 to/created。因此,它需要一种资源(例如 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
库 as outlined in this question。
不幸的是,生产服务器并不是那么容易添加库。因此,我发现自己在寻找不同的解决方案。
我在其他项目中使用过 phpseclib
,但仅用于基本 get()
、put()
和一些 nlist()
调用。
为了让它工作,我不得不使用一个 Stream
对象。没有很好的记录,但有 a good discussion here.
根据那里的信息,加上在 SFTP
class 中的一些挖掘,特别是 get()
函数,这就是我使用 [= 实现相同功能的方法14=]
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);
注意 fopen()
调用中 sftp://
之后的点 (.
)。浪费了我半个小时!
这就是我使用 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);
我想使用 PHP 读取远程文本文件(最好使用 fopen)。当我在本地文件上使用此函数时,我的脚本使用 fopen 工作。
我试过:
$file = fopen ("http://abc.abc.abc", "r");
if (!$file) {
echo "<p>Unable to open remote file.\n";
exit;
}
我得到了:
Warning: fopen(http://abc.abc.abc): failed to open stream: No connection could be made because the target machine actively refused it. in C:\xampp\htdocs\NMR\nmrTest5.php on line 2 Unable to open remote file.
我读到 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');
}
我得到了:
Notice: No compatible server to client encryption algorithms found in C:\xampp\htdocs\NMR\Net\SSH2.php on line 1561 Login Failed
有趣的是,如果我连接到服务器(使用 WinSCP),我会收到不同的消息:
Notice: Error reading from socket in C:\xampp\htdocs\NMR\Net\SSH2.php on line 3362
Notice: Connection closed by server in C:\xampp\htdocs\NMR\Net\SSH2.php on line 1471 Login Failed
知道如何让它工作吗?理想情况下我会使用 fopen 但我愿意接受其他解决方案。
我遇到过与 fopen 类似的问题。 Curl 可用于这些目的。
请检查以下基本示例函数(如果 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;
}
我自己一直在解决这个确切的问题,但在任何一个地方都找不到任何关于如何完成这个问题的好文档。
我刚刚制作了一个使用 Monolog 的日志记录服务,并且基本上根据正在写入的日志文件制作了一个自定义流处理程序 to/created。因此,它需要一种资源(例如 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
库 as outlined in this question。
不幸的是,生产服务器并不是那么容易添加库。因此,我发现自己在寻找不同的解决方案。
我在其他项目中使用过 phpseclib
,但仅用于基本 get()
、put()
和一些 nlist()
调用。
为了让它工作,我不得不使用一个 Stream
对象。没有很好的记录,但有 a good discussion here.
根据那里的信息,加上在 SFTP
class 中的一些挖掘,特别是 get()
函数,这就是我使用 [= 实现相同功能的方法14=]
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);
注意 fopen()
调用中 sftp://
之后的点 (.
)。浪费了我半个小时!
这就是我使用 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);