超时后恢复FTP下载

8

我正在从一个不稳定的FTP服务器下载文件,经常在文件传输过程中超时,我想知道是否有一种方法可以重新连接并恢复下载。我正在使用Python的ftplib。以下是我使用的代码:

#! /usr/bin/python

import ftplib
import os
import socket
import sys

#--------------------------------#
# Define parameters for ftp site #
#--------------------------------#
site           = 'a.really.unstable.server'
user           = 'anonymous'
password       = 'someperson@somewhere.edu'
root_ftp_dir   = '/directory1/'
root_local_dir = '/directory2/'

#---------------------------------------------------------------
# Tuple of order numbers to download. Each web request generates 
# an order numbers
#---------------------------------------------------------------
order_num = ('1','2','3','4')

#----------------------------------------------------------------#
# Loop through each order. Connect to server on each loop. There #
# might be a time out for the connection therefore reconnect for #
# every new ordernumber                                          #
#----------------------------------------------------------------#
# First change local directory
os.chdir(root_local_dir)

# Begin loop through 
for order in order_num:
    
    print 'Begin Proccessing order number %s' %order
    
    # Connect to FTP site
    try:
        ftp = ftplib.FTP( host=site, timeout=1200 )
    except (socket.error, socket.gaierror), e:
        print 'ERROR: Unable to reach "%s"' %site
        sys.exit()
    
    # Login
    try:
        ftp.login(user,password)
    except ftplib.error_perm:
        print 'ERROR: Unable to login'
        ftp.quit()
        sys.exit()
     
    # Change remote directory to location of order
    try:
        ftp.cwd(root_ftp_dir+order)
    except ftplib.error_perm:
        print 'Unable to CD to "%s"' %(root_ftp_dir+order)
        sys.exit()

    # Get a list of files
    try:
        filelist = ftp.nlst()
    except ftplib.error_perm:
        print 'Unable to get file list from "%s"' %order
        sys.exit()
    
    #---------------------------------#
    # Loop through files and download #
    #---------------------------------#
    for each_file in filelist:
        
        file_local = open(each_file,'wb')
        
        try:
            ftp.retrbinary('RETR %s' %each_file, file_local.write)
            file_local.close()
        except ftplib.error_perm:
            print 'ERROR: cannot read file "%s"' %each_file
            os.unlink(each_file)
        
    ftp.quit()
    
    print 'Finished Proccessing order number %s' %order
    
sys.exit()

我收到的错误信息是:

socket.error: [Errno 110] 连接超时

如果您能提供帮助,将不胜感激。

一定要查看http://ftputil.sschwarzer.net/trac,它将使任何与ftp相关的任务更加容易。 - agf
3个回答

4
通过仅使用标准设备(参见RFC959)恢复FTP下载需要使用块传输模式(第3.4.2节),可以使用MODE B命令进行设置。虽然此功能在技术上要求符合规范,但我不确定所有FTP服务器软件是否实现了它。
在块传输模式下,与流传输模式相反,服务器以块的形式发送文件,每个块都有一个标记。该标记可以重新提交到服务器以重新启动失败的传输(第3.5节)。
规范说:

[...]提供了重启过程,以保护用户免受严重的系统故障(包括主机故障、FTP进程故障或底层网络故障)。

但是,据我所知,规范并未定义标记的必需寿命。它只说了以下内容:

标记信息只对发送方有意义,但必须由控制连接的默认或协商语言(ASCII或EBCDIC)中的可打印字符组成。标记可以表示位数、记录数或任何其他系统可以通过其识别数据检查点的信息。如果接收数据的人实现了重新启动过程,则会在接收系统中标记此标记的相应位置,并将此信息返回给用户。

可以安全地假定实现此功能的服务器将提供在FTP会话之间有效的标记,但您的情况可能有所不同。


2
使用Python ftplib实现可恢复的FTP下载的简单示例:
def connect():

ftp = None

with open('bigfile', 'wb') as f:
    while (not finished):
        if ftp is None:
            print("Connecting...")
            FTP(host, user, passwd)

        try:
            rest = f.tell()
            if rest == 0:
                rest = None
                print("Starting new transfer...")
            else:
                print(f"Resuming transfer from {rest}...")
            ftp.retrbinary('RETR bigfile', f.write, rest=rest)
            print("Done")
            finished = True
        except Exception as e:
            ftp = None
            sec = 5
            print(f"Transfer failed: {e}, will retry in {sec} seconds...")
            time.sleep(sec)

更加细致的异常处理是可取的。
同样适用于上传:
处理Python ftplib FTP上传文件中的断开连接

-1
要做到这一点,您必须保持被中断的下载状态,然后确定您缺少哪些文件部分,下载这些部分,然后将它们连接在一起。我不确定如何做到这一点,但是Firefox和Chrome都有一个名为DownThemAll的下载管理器可以执行此操作。虽然该代码不是用Python编写的(我认为是JavaScript),但您可以查看该代码并了解它是如何实现的。
DownThemAll - http://www.downthemall.net/

DownThemAll是用JavaScript和XUL(XML用户界面语言)编写的。来源- http://en.wikipedia.org/wiki/DownThemAll! 和 https://github.com/nmaier/DownThemAll - Neil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接