2011-08-03 16 views
6

Pobieram pliki z niestabilnego serwera FTP, który często kończy się podczas przesyłania plików i zastanawiałem się, czy istnieje sposób na ponowne połączenie i wznowienie pobierania. Używam ftplib Pythona. Oto kod, który używam:Wznów pobieranie FTP po przekroczeniu limitu czasu

#! /usr/bin/python 

import ftplib 
import os 
import socket 
import sys 

#--------------------------------# 
# Define parameters for ftp site # 
#--------------------------------# 
site   = 'a.really.unstable.server' 
user   = 'anonymous' 
password  = '[email protected]' 
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() 

Błąd, który pojawia się: socket.error: [errno 110] Connection timed out

Każda pomoc jest mile widziana.

+0

Zdecydowanie sprawdź http://ftputil.sschwarzer.net/trac, to sprawi, że każde zadanie związane z FTP będzie łatwiejsze. – agf

Odpowiedz

3

wznawianie pobierania przez FTP używając tylko standardowe wyposażenie (patrz RFC959) wymaga użycia trybu transmisji bloku (sekcja 3.4.2), który można ustawić za pomocą komendy MODE B. Chociaż ta funkcja jest technicznie wymagana dla zgodności ze specyfikacją, nie jestem pewien, czy wszystkie oprogramowanie serwera FTP ją implementuje.

W trybie transmisji blokowej, w przeciwieństwie do trybu przesyłania strumieniowego, serwer wysyła plik w porcjach, z których każdy ma znacznik. Ten znacznik może zostać ponownie przesłany do serwera w celu ponownego uruchomienia nieudanego transferu (sekcja 3.5).

Specyfikacja mówi:

[...] a restart procedure is provided to protect users from gross system failures (including failures of a host, an FTP-process, or the underlying network).

Jednak AFAIK, specyfikacja nie określa wymaganej trwałości markerów. To tylko mówi, co następuje:

The marker information has meaning only to the sender, but must consist of printable characters in the default or negotiated language of the control connection (ASCII or EBCDIC). The marker could represent a bit-count, a record-count, or any other information by which a system may identify a data checkpoint. The receiver of data, if it implements the restart procedure, would then mark the corresponding position of this marker in the receiving system, and return this information to the user.

Powinno być bezpiecznie założyć, że serwery wdrażające tę funkcję dostarczy znaczniki, które są ważne w okresie od sesji FTP, ale może się wahać.

0

Aby to zrobić, musisz zatrzymać przerwane pobieranie, a następnie dowiedzieć się, które części pliku brakuje, pobrać te części, a następnie połączyć je ze sobą. Nie jestem pewien, jak to zrobić, ale istnieje menedżer pobierania dla przeglądarki Firefox i Chrome o nazwie DownThemAll, który to robi. Chociaż kod nie jest napisany w pythonie (myślę, że jest to JavaScript), możesz spojrzeć na kod i zobaczyć, jak to działa.

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

+0

DownThemAll jest napisany w JavaScript i XUL (XML User Interface Language). Źródło- http://pl.wikipedia.org/wiki/DownThemAll! i https://github.com/nmaier/DownThemAll – Neil

Powiązane problemy