ftplib python:NOOP命令在ASCII而不是二进制中工作



我有一个线程FTP脚本。当数据套接字接收数据时,线程循环将 NOOP 命令发送到控制套接字,以在大型传输期间保持控制连接处于活动状态。

我无法使用 FTP.retrbinary() 命令,因为如果我想保持控制连接处于活动状态,我必须将数据和控制套接字分开,而retrbinary不会这样做。

代码如下:

def downloadFile(filename, folder):
    myhost = 'HOST'
    myuser = 'USER'
    passw = 'PASS'
    #login
    ftp = FTP(myhost,myuser,passw)
    ftp.set_debuglevel(2)
    ftp.voidcmd('TYPE I')
    sock = ftp.transfercmd('RETR ' + filename)
    def background():
        f = open(folder + filename, 'wb')
        while True:
            block = sock.recv(1024*1024)
            if not block:
                break
            f.write(block)
        sock.close()
    t = threading.Thread(target=background)
    t.start()
    while t.is_alive():
        t.join(120)
        ftp.voidcmd('NOOP')
    ftp.quit();


我的问题FTP.transfercmd("RETR " + filename)默认为 ASCII 传输和 Im 传输视频,因此它必须是二进制的(因此ftp.voidcmd('TYPE I)调用强制二进制模式)。

如果我调用ftp.voidcmd('TYPE I)则 NOOP 命令将成功发送,输出如下:

*cmd* 'NOOP'
*put* 'NOOPrn'
*get* '200 NOOP: data transfer in progressn'
*resp* '200 NOOP: data transfer in progress'
*cmd* 'NOOP'
*put* 'NOOPrn'
*get* '200 NOOP: data transfer in progressn'
*resp* '200 NOOP: data transfer in progress'
*cmd* 'NOOP'
*put* 'NOOPrn'
*get* '200 NOOP: data transfer in progressn'
*resp* '200 NOOP: data transfer in progress'

等。但是该文件是ASCII格式,因此已损坏。如果我确实调用ftp.voidcmd('TYPE I),NOOP 命令只发送一次,并且在传输完成之前控制套接字没有响应。如果文件很大,控制套接字会超时,就好像 NOOP 从未发送过一样......

很奇怪,但我相信它很简单。似乎transfercmd()并没有像预期的那样拆分控件和数据套接字......因此,FTP VaR 不会与数据流分离...什么的。奇怪。

提前感谢您提供的任何建议。

tcpdump确认服务器仅在服务器发送整个文件后发送226 Transfer complete.

我怀疑这是FTP规范的一部分。

实际上,请查看ftplib.py中的retrbinary代码:

    self.voidcmd('TYPE I')
    conn = self.transfercmd(cmd, rest)
    while 1:
        data = conn.recv(blocksize)
        if not data:
            break
        callback(data)
    conn.close()
    return self.voidresp()

最后一行期望仅在传输完成后获得传输结果(服务器已知)。

事实上,您的代码似乎缺少voidresp()位。

我对ftp不是很熟悉,从我所看到的后台下载器来看lftp实际上为每个并行下载打开了新的控制连接。

如果您的文件真的很大,您有理由担心。

FTP有许多扩展,可能有一些东西可以做你想要的。

或者,您可以像这样制作一个循环:

pos = 0
while not full file:
    command REST
    download for a while in separate thread
    command ABRT
    wait for separate thread to abort
    pos += length of downloaded chunk

相关内容

  • 没有找到相关文章

最新更新