FTP 的“断点续传”

  最近写了个 FTP 上传程序,考虑到网络断线等因素造成的上传中断,所以打算给这个程序加个“断点续传”的功能,说是断点续传,其实跟现在 FlashGet 或者迅雷等下载工具的断点续传还是不一样的,我这里断点续传指的是断线以后只上传刚才还没有被上传的和没有完整上传的文件。比如总共有 100 个文件需要上传,只完整上传了 49 个文件,在第 50 个文件只传了一半的时候断线了,那么再次连接之后只需要重新上传第 50 个文件和后面 50 个文件就可以啦。

  为了达到这个目的,只要等取到 FTP 上的文件列表就 OK。初次使用 Python 的 ftplib,尝试了几种方法,FTP.nlst() 只能拿到文件名,拿不到文件大小。最后决定用 FTP.retrlines() 搞定,但是这个接口的麻烦之处是需要一个 callback 来接收从 server 返回的每一行,对 C/C++ 这类语言来说,由于涉及两个函数调用过程,所以上下文关联稍稍有些麻烦,但是 Python 的 lambda 用在这里真是方便(话又说回来,FTP.retrlines() 直接返回一个 tuple 或者 list 不是更干脆?)。

  1. def GetFileInfo( ftp ):
  2.      file_list = []
  3.      try:
  4.          ftp.retrlines( 'LIST', lambda item: file_list.append( item ) )
  5.      except:
  6.          return( {} )
  7.  
  8.      ro = re.compile( '(.).{9}\s+\d+\s+(?:[^ ]+\s+){2}(\d+)\s+(?:[^ ]+\s+){3}(.+)' )
  9.      file_info = {}
  10.  
  11.      for item in file_list:
  12.          m = ro.match( item )
  13.          if m:
  14.              file_info[m.group(3)] = [ m.group(1), m.group(2) ]
  15.  
  16.      return( file_info )

这个函数返回一个 dictionary,然后对于一个本地文件,用 if file in file_info 就能判断 server 上是否已经有了这个文件,有的话,file_info[file][1] 就是 server 上这个文件的大小,这个大小跟本地文件大小不符就重新上传。

Leave a Reply