Ftp 正确使用STOR命令

Ftp 正确使用STOR命令,ftp,Ftp,我需要从ftp服务器获取响应消息,我正在对连接进行故障排除,因此我使用PHP的ftp\u raw函数,它允许我向远程服务器发送原始ftp命令,并获取响应字符串。(内置PHP ftp命令不返回响应:( 根据已接受的答案,我发送的命令是 PASV STOR /local/path/to/file.txt 服务器响应是 500 /local/path/to/file.txt: The system cannot find the path specified. 我在想,“当然,远程主机不知道我的本

我需要从ftp服务器获取响应消息,我正在对连接进行故障排除,因此我使用PHP的
ftp\u raw
函数,它允许我向远程服务器发送原始ftp命令,并获取响应字符串。(内置PHP ftp命令不返回响应:(

根据已接受的答案,我发送的命令是

PASV
STOR /local/path/to/file.txt
服务器响应是

500 /local/path/to/file.txt: The system cannot find the path specified.
我在想,“当然,远程主机不知道我的本地文件系统。”我的直觉是,我正在打开一个套接字,指定一个远程文件名,我仍然需要通过管道传输数据。但在搜索过程中,我在文档中没有找到任何结论

上传文件的完整原始ftp命令集是什么?在什么点,以及如何开始向远程服务器发送数据?我可以使用从
ftp\u connect()
设置的连接作为套接字吗?

工作解决方案(使用端口完全重写早期解决方案)。正确的顺序是

PASV
Server responds with something like
"227 Entering Passive Mode (127,0,0,1,30,235)"
STOR /path/on/remote/server/foo.txt
=> Now we have to connect to socket 30*256+235 on 127.0.0.1 and send the data.
Done
代码


免责声明:首先要知道的是,这是在FTP流行一段时间后编写的,在RFC959发布之前(以及发布后一段时间),由于缺乏规范,仍然存在一些损坏的软件。许多旧软件(更稳定)FTP库对某些服务器有一些特殊的处理,以确保它在99.9%的时间内以您希望的方式工作。这在处理FTP协议的扩展时尤其常见

我回答的其余部分假设服务器符合RFC959

还请记住,绕过FTP客户端库的更高级别请求/响应管理意味着您需要自己重新实现该库的一部分。这意味着您应该熟悉该规范,因为您需要参考它。如果可能,我将参考相应的部分,以便您可以了解

在这种情况下,我强烈建议您通过进入PHP的FTP客户端库来调试您的问题,而不是自己实现所有这些。有可能,您真的应该请求该库输出它使用的所有命令。尽管如此,我仍将指导您完成该过程,以帮助诊断您的问题。


管理FTP数据连接有点困难。如果您想支持规范的所有可选部分,这并不像乍一看那么容易。传输文件的具体方式主要取决于以下选项的当前状态:

  • 数据类型(第3.1.1节):使用图像/二进制数据类型传输文件通常是最安全和最有效的。这不是默认值,某些FTP命令(如目录列表)要求将其设置为ASCII,因此请确保在传输之前始终将其设置为ASCII
  • 数据结构(第3.1.2节):文件结构通常是您想要的,但一些较旧的计算机和大型机可能必须转换为该模式或从该模式转换
  • 传输模式(第3.4节):流模式是最常用的,但块模式支持恢复中断传输,而压缩模式则不受关注
  • 连接模式(第3.2节和第3.3节):客户机或服务器可以通过连接到其对等机来建立数据连接。这必须通过以下方式协商:
    • 默认值:客户端侦听端口20;或
    • 自定义端口:客户端告诉服务器它在另一个端口上列出;或者
    • 被动模式:客户端询问服务器将在哪个端口上侦听
  • 请注意规范,因为某些配置允许您保持数据连接打开,而其他配置可能需要您关闭数据连接(例如流模式)。如果数据连接已打开,则不需要在每次传输时重新连接到服务器


    所有这些看起来都很复杂,但它只是提供了一些信息。在调试过程中,它可能会派上用场。使用FTP传输文件的常用方法只有两种:

  • 服务器通过第二个端口连接到客户机,并使用文件数据结构以图像(二进制)数据类型发送文件

  • 配置数据类型(必需):

    第一类

  • 配置数据结构(可选,默认):

    STRU F

  • 配置传输模式(可选,默认):

    模式S

  • 选择一个可用端口(这可能比您想象的要微妙一些)并开始侦听。如果选择默认端口(20),请跳过下一步

    选择端口,创建套接字,监听所选端口

  • 告诉服务器我们将在给定的端口上侦听(如果选择了默认端口,则为可选,但小心也无妨):

    端口您的公共ip地址,所选端口

  • 告诉服务器希望进行文件传输:

    STOR远程文件名

  • 等待来自服务器的传入连接

  • 发送文件内容

    打开文件、发送内容、关闭文件

  • 关闭数据连接

    合上插座

  • 客户端通过第二个端口连接到服务器,并使用文件数据结构以图像(二进制)数据类型发送文件

  • 配置数据类型(必需):

    第一类

  • 配置数据结构(可选,默认):

    STRU F

  • 配置传输模式(可选,默认):

    模式S

  • 告诉服务器我们将在给定端口上侦听(必需):

    PASV

  • 读取包含服务器正在侦听的IP地址和端口号的
    PASV
    命令响应

  • 告诉服务器希望进行文件传输:

    STOR远程文件名

  • $fp = ftp_connect("127.0.0.1", 21, 10) or die("foo"); ftp_login ($fp, "anonymous", "password"); ftp_raw_send_file($fp, "/local/path/to/file.txt", "foo/foo.txt"); function ftp_raw_send_file($fp, $localfile, $remotefile) { $connect = ftp_raw($fp, "PASV"); // parse the response and build the IP and port from the values if (count($connect) > 0 && preg_match("/.*\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)/", $connect[0], $m)) { $address="{$m[1]}.{$m[2]}.{$m[3]}.{$m[4]}"; $port=$m[5] * 256 + $m[6]; print_r(ftp_raw($fp, "STOR $remotefile")); $sock = socket_create(AF_INET, SOCK_STREAM, 0); if ($sock) { socket_connect($sock, $address, $port); socket_write($sock, file_get_contents($localfile)); socket_close($sock); } } }