【问题标题】:Python ftp stor freezesPython ftp 存储冻结
【发布时间】:2024-01-16 17:48:01
【问题描述】:

我在使用 python 中的脚本通过 TLS 将一些文件上传到 ftp 时遇到了一些问题。我使用以下代码:

ftps = FTP_TLS(FTP_SERVER)
ftps.set_debuglevel(2)
ftps.login(FTP_USER,FTP_PASSWORD)
ftps.prot_p()
ftps.cwd(DIR)
ftps.storlines("STOR " + filename, open(file))

此时脚本似乎冻结了。例如,如果我通过 filezilla 登录 ftp 服务器,我可以看到创建的文件,但大小为 0Kb。我用 Ctrl+C 取消脚本,然后文件在 filezilla 中显示为正确的大小。如果我让脚本完成文件在 ftp 服务器上被删除。

调试输出是这样的:

*cmd* 'AUTH TLS'
*put* 'AUTH TLS\r\n'
*get* '234 AUTH command ok. Expecting TLS Negotiation.\r\n'
*resp* '234 AUTH command ok. Expecting TLS Negotiation.'
*cmd* 'USER XXXXXXXXX'
*put* 'USER XXXXXXXXX\r\n'
*get* '331 Password required\r\n'
*resp* '331 Password required'
*cmd* 'PASS **************'
*put* 'PASS **************\r\n'
*get* '230-congrats\r\n'
*get* '230 User logged in.\r\n'
*resp* '230-congrats\n230 User logged in.'
*cmd* 'PBSZ 0'
*put* 'PBSZ 0\r\n'
*get* '200 PBSZ command successful.\r\n'
*resp* '200 PBSZ command successful.'
*cmd* 'PROT P'
*put* 'PROT P\r\n'
*get* '200 PROT command successful.\r\n'
*resp* '200 PROT command successful.'
*cmd* 'CWD XXXXXXXXX'
*put* 'CWD XXXXXXXXX\r\n'
*get* '250 CWD command successful.\r\n'
*resp* '250 CWD command successful.'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A.\r\n'
*resp* '200 Type set to A.'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (XXXXXXXXXXXXXX).\r\n'
*resp* '227 Entering Passive Mode (XXXXXXXXXXXX).'
*cmd* 'STOR file.txt'
*put* 'STOR file.txt\r\n'
*get* '125 Data connection already open; Transfer starting.\r\n'
*resp* '125 Data connection already open; Transfer starting.'
^C
*cmd* 'QUIT'
*put* 'QUIT\r\n'
*get* '226 Transfer complete.\r\n'
*resp* '226 Transfer complete.'

脚本在此时冻结:

*resp* '125 Data connection already open; Transfer starting.'

有什么想法可能是错的吗?

【问题讨论】:

  • 会不会是被动配置的问题?也许您可以在调用storlines之前尝试使用ftps.set_pasv(False) 进行配置
  • 如果我将 pasv 设置为 False,我会收到错误消息:ftplib.error_perm: 501 Server cannot accept argument.
  • 只是为了确保输入文件没有问题,你可以试试:import io txtfile = io.StringIO(u"abc\ndefgh\nijkl\n") 然后ftps.storlines("STOR " + filename, txtfile)
  • 同样的结果,挂在这里:*get* '125 数据连接已经打开;传输开始。\r\n' resp '125 数据连接已打开;转移开始。
  • 你控制 ftpserver 和它的网络吗?它是什么服务器?

标签: python ftp ftplib


【解决方案1】:

我可以设置一个 TLS 服务器并使用与 python 2.7 完全相同的命令。

一切顺利。我得到的答案略有不同,因为我认为我不使用与您相同的服务器。在storelines 命令处事情开始变得真正不同了(我使用with 来确保该文件将被关闭):

with open(filename) as fd:
    ftps.storlines("STOR foo.txt", fd)


*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A.\r\n'
*resp* '200 Type set to A.'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (192,168,56,48,227,80)\r\n'
*resp* '227 Entering Passive Mode (192,168,56,48,227,80)'
*cmd* 'STOR foo.txt'
*put* 'STOR foo.txt\r\n'
*get* "150 Opening ASCII mode SSL data connection for 'foo.txt'.\r\n"
*resp* "150 Opening ASCII mode SSL data connection for 'foo.txt'."
*get* '226 Transfer complete.\r\n'
*resp* '226 Transfer complete.'
'226 Transfer complete.'

主要区别在于,当您收到 125 Data connection already open; Transfer starting. 时,我收到的是 150 Opening ASCII mode SSL data connection

我的结论是您的客户端脚本不是原因,因为它可以在我的计算机上运行,​​而是服务器 FTPD 或两者之间的网络问题(代理?)。但我不喜欢125 Data connection already open

编辑:

我在 Python 3.4 下也一样,但需要以二进制模式打开本地文件:

with open(filename, 'rb') as fd:
    ftps.storlines("STOR foo.txt", fd)

同样的输出...

【讨论】:

  • 谢谢,我无法控制服务器端,但我可以与他们交谈,他们改变了一些东西,现在它可以工作了。他们使用 IIS 7。