Возобновить загрузку FTP после тайм-аута


Я загружаю файлы с облупленного FTP-сервера, который часто отключается во время передачи файлов, и мне было интересно, есть ли способ восстановить соединение и возобновить загрузку. Я использую ftplib python. Вот код, который я использую:

#! /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()

Ошибка, которую я получаю: сокет.ошибка: [Errno 110] время ожидания соединения истекло

Любая помощь очень ценится.

2 6

2 ответа:

Возобновление загрузки через FTP с использованием только стандартных средств (см.RFC959 ) требует использования блочного режима передачи (раздел 3.4.2), который может быть установлен с помощью команды MODE B. Хотя эта функция технически необходима для соответствия спецификации, я не уверен, что все программное обеспечение FTP-сервера реализует ее.

В режиме блочной передачи, в отличие от режима потоковой передачи, сервер отправляет файл кусками, каждый из которых имеет маркер. Этот маркер может быть повторно отправлен на сервер для перезапуска неудачной передачи (раздел 3.5).

Спецификация гласит:

[... процедура перезапуска предназначена для защиты пользователей от грубых системных сбоев (включая сбои хоста, FTP-процесса или базовой сети).

Однако, AFAIK, спецификация не определяет необходимое время жизни для маркеров. Он говорит только следующее:

Маркерная информация имеет значение только для отправителя, но должен состоять из печатаемых символов на языке по умолчанию или согласованном языке управляющего соединения (ASCII или EBCDIC). Маркер может представлять собой число битов, число записей или любую другую информацию, по которой система может идентифицировать контрольную точку данных. Получатель данных, если он реализует процедуру перезапуска, будет затем отмечать соответствующее положение этого маркера в приемной системе и возвращать эту информацию пользователю.

Можно с уверенностью предположить, что серверы реализация этой функции обеспечит маркеры, которые действительны между сеансами FTP, но ваш пробег может отличаться.

Для этого вам нужно сохранить прерванную загрузку, затем выяснить, какие части файла вы пропускаете, загрузить эти части и затем соединить их вместе. Я не знаю, как это сделать, но есть менеджер загрузок для Firefox и Chrome под названием DownThemAll, который делает это. Хотя код написан не на python (я думаю, что это JavaScript), вы можете посмотреть на код и посмотреть, как он это делает.

DownThemll - http://www.downthemall.net/