文件传输过程中经常需要使用FTP服务器进行中转。Python集成了ftp模块,可以比较方便的实现一个ftp客户端。本文主要实现了递归上传或下载, 文件和文件夹。isExist可以判断ftp服务器上是否存在某一路径,如果存在,可以进一步判定出它是文件还是文件夹。
__mail__ = 'xudacheng06@163.com' __date__ = '2014-04-23' __version = 1.2 import sys import os import time from ftplib import * _XFER_FILE = 'FILE' _XFER_DIR = 'DIR' _XFER_NONE = "NONE" class Xfer(object): ''' @note: upload local file or dirs recursively to ftp server ''' def __init__(self): self.ftp = None def __del__(self): pass def setFtpParams(self, ip, uname, pwd, port = 21, timeout = 60): self.ip = ip self.uname = uname self.pwd = pwd self.port = port self.timeout = timeout def initEnv(self): if self.ftp is None: self.ftp = FTP() print '### connect ftp server: %s ...'%self.ip if sys.version_info < (2,7,0): self.ftp.connect(self.ip, self.port) else: self.ftp.connect(self.ip, self.port, self.timeout) self.ftp.login(self.uname, self.pwd) print self.ftp.getwelcome() def clearEnv(self): if self.ftp: self.ftp.close() print '### disconnect ftp server: %s!'%self.ip self.ftp = None def isExist(self, remotepath): ''' if remoetepath exists, return TRUE and the type of remotepath, FILE or DIR else return (FALSE, NONE) ''' def parse(line): pass bExist = False if self.ftp: try: self.ftp.dir(remotepath, parse) bExist = True except: pass if bExist: res = self.ftp.nlst(remotepath) if len(res) == 0 or len(res) > 1 or len(res[0]) > len(remotepath): return True, _XFER_DIR return True, _XFER_FILE return False, _XFER_NONE def uploadFile(self, localpath, remotepath=None): ''' @note: assume localpath is 'c:\log.txt' and remotepath is '/xx/log.txt', then /xx dir must exists ''' if not os.path.isfile(localpath): sys.stderr.write("--- %r doesn't exist"%localpath) return if remotepath: index = remotepath.rfind('\\') if index == -1: index = remotepath.rfind('/') if index != -1: basedir = remotepath[:index] bExist, sType = self.isExist(basedir) if not bExist or sType != _XFER_DIR: sys.stderr.write("--- %r doesn't exist"%basedir) return curdir = "" if not remotepath.startswith("/"): curdir = self.ftp.pwd() if not curdir.endswith("/"): curdir += '/' print '+++ upload %s to %s:%s%s'%(localpath, self.ip, curdir, remotepath) self.ftp.storbinary('STOR ' + remotepath, open(localpath, 'rb')) def uploadDir(self, localdir='./', remotedir='./'): if not os.path.isdir(localdir): sys.stderr.write("--- %r doesn't exist"%localdir) return if not remotedir.endswith('/'): remotedir += '/' #if remotedir doesn't exist, create one try: def parse(line): pass self.ftp.dir(remotedir, parse) except: self.ftp.mkd(remotedir) curdir = self.ftp.pwd() self.ftp.cwd(remotedir) for file in os.listdir(localdir): src = os.path.join(localdir, file) if os.path.isfile(src): self.uploadFile(src, file) elif os.path.isdir(src): bExist, sType = self.isExist(file) if not bExist: self.ftp.mkd(file) elif sType != _XFER_DIR: sys.stderr.write('--- file %r exists, not a directory'%file) continue self.uploadDir(src, remotedir+file) self.ftp.cwd(curdir) def downloadFile(self, remotepath, localDir): curdir = self.ftp.pwd() if not curdir.endswith('/'): curdir += '/' if not remotepath.startswith("/"): remotepath = curdir + remotepath bExist, sType = self.isExist(remotepath) if not bExist: sys.stderr.write("--- %r:%r doesn't exist"%(self.ip, remotepath)) return if sType != _XFER_FILE: sys.stderr.write("--- %r:%r is not a file"%(self.ip, remotepath)) return if not os.path.isdir(localDir): sys.stderr.write("--- %r doesn't exist"%localDir) return if not localDir.endswith("/") and not localDir.endswith("\\"): localDir = localDir + '/' temp = remotepath.split("/") filename = temp[len(temp)-1] dst = localDir + filename remotedir = remotepath[:remotepath.rfind(filename)] self.ftp.cwd(remotedir) f = open(dst,"wb") print "+++ download %r:%r to %s"%(self.ip, remotepath, dst) self.ftp.retrbinary("RETR %s"%filename, f.write) f.close() self.ftp.cwd(curdir) return True def downloadDir(self, remoteDir, localDir): if not os.path.isdir(localDir): os.mkdir(localDir) if not localDir.endswith("/") and not localDir.endswith("\\"): localDir = localDir + '/' bExist, sType = self.isExist(remoteDir) if not bExist: sys.stderr.write("--- %r:%r doesn't exist"%(self.ip, remoteDir)) return if sType != _XFER_DIR: sys.stderr.write("--- %r:%r is not a dir"%(self.ip, remoteDir)) return curdir = self.ftp.pwd() if not curdir.endswith('/'): curdir += '/' if not remoteDir.startswith("/"): remoteDir = curdir + remoteDir if not remoteDir.endswith("/"): remoteDir = remoteDir + '/' for file in self.ftp.nlst(remoteDir): bExist, sType = self.isExist(file) if not bExist: sys.stderr.write("--- %r:%r doesn't exist"%(self.ip, file)) return if sType == _XFER_DIR: temp = file.split("/") filename = temp[len(temp)-1] self.downloadDir(file, localDir+filename) continue self.downloadFile(file, localDir) if __name__ == '__main__': xfer = Xfer() xfer.setFtpParams('127.0.0.1', 'root', 'root') xfer.initEnv() print xfer.isExist("/") xfer.uploadFile("clsLoader.py", '/xx/clsLoader.py') xfer.uploadDir('urllibTst', '/yy/zz') xfer.downloadFile('yy/tst1.py', 'D:/') print xfer.downloadDir("yy", "d:\\xxxx\\zz") xfer.clearEnv()