#coding:utf-8
__author__ = 'similarface'
importos, sys, ftplibfrom getpass importgetpassfrom mimetypes importguess_type, add_type
dfltSite= '192.168.30.252'dfltRdir= '.'dfltUser= 'child'
classFtpTools:#allow these 3 to be redefined
defgetlocaldir(self):return (len(sys.argv) > 1 and sys.argv[1]) or '.'
defgetcleanall(self):#return raw_input('Clean target dir first?')[:1] in ['y','Y']
returnFalsedefgetpassword(self):return getpass('Password for %s on %s:' %(self.remoteuser, self.remotesite))def configTransfer(self, site=dfltSite, rdir=dfltRdir, user=dfltUser,ldir=''):"""获取上传下载的参数
from module defaults, args, inputs, cmdline anonymous ftp: user='anonymous' pass=emailaddr"""self.nonpassive=False
self.remotesite=site
self.remotedir=rdir
self.remoteuser=user#self.localdir=self.getlocaldir()
self.localdir=ldir
self.cleanall=self.getcleanall()
self.remotepass=self.getpassword()
def isTextKind(self, remotename, trace=True):
add_type('text/x-python-win', '.pyw')
mimetype, encoding= guess_type(remotename, strict=False)
mimetype= mimetype or '?/?'maintype= mimetype.split('/')[0]if trace: print(maintype, encoding or '')return maintype == 'text' and encoding ==NonedefconnectFtp(self):print('connecting...')
connection=ftplib.FTP(self.remotesite)
connection.login(self.remoteuser, self.remotepass)try:
connection.cwd(self.remotedir)exceptException,e:printe
connection.mkd(self.remotedir)
connection.cwd(self.remotedir)ifself.nonpassive:
connection.set_pasv(False)
self.connection=connectiondefcleanLocals(self):"""尝试删除所有的本地文件"""
ifself.cleanall:#本地文件的遍历
for localname inos.listdir(self.localdir):try:#本地文件删除
print('deleting local', localname)
os.remove(os.path.join(self.localdir, localname))except:print('cannot delete local', localname)defcleanRemotes(self):"""尝试删除所有远程文件为移除无效文件"""
ifself.cleanall:for remotename inself.connection.nlst():try:print('deleting remote', remotename)
self.connection.delete(remotename)except:#remote dir listing # remote file delete
print('cannot delete remote', remotename)defdownloadOne(self, remotename, localpath):"""download one file by FTP in text or binary mode local name need not be same as remote name
使用FTP下载一个文件
remotename:远程文件
localpath:本地文件"""
ifself.isTextKind(remotename):
localfile= open(localpath, 'w', encoding=self.connection.encoding)def callback(line): localfile.write(line + '\n')#RETR表示下载命令 callback表示回调
self.connection.retrlines('RETR' +remotename, callback)else:
localfile= open(localpath, 'wb')
self.connection.retrbinary('RETR' +remotename, localfile.write)
localfile.close()defuploadOne(self, localname, localpath, remotename):"""upload one file by FTP in text or binary mode remote name need not be same as local name
使用FTP上传一个文件"""
ifself.isTextKind(localname):
localfile= open(localpath, 'rb')#STOR表示上传
self.connection.storlines('STOR' +remotename, localfile)else:
localfile= open(localpath, 'rb')
self.connection.storbinary('STOR' +remotename, localfile)
localfile.close()defdownloadDir(self):"""从远程下载所有的文件
download all files from remote site/dir per config
ftp nlst() gives files list, dir() gives full details"""remotefiles= self.connection.nlst() #nlst is remote listing
for remotename inremotefiles:if remotename in ('.', '..'): continuelocalpath=os.path.join(self.localdir, remotename)#print('downloading', remotename, 'to', localpath, 'as', end=' ')
self.downloadOne(remotename, localpath)print('Done:', len(remotefiles), 'files downloaded.')defuploadDir(self):"""upload all files to remote site/dir per config
listdir() strips dir path, any failure ends script
上传一个目录"""localfiles= os.listdir(self.localdir) #listdir is local listing
for localname inlocalfiles:
localpath=os.path.join(self.localdir, localname)print('uploading', localpath, 'to', localname, 'as')
self.uploadOne(localname, localpath, localname)print('Done:', len(localfiles), 'files uploaded.')def run(self, cleanTarget=lambda:None, transferAct=lambda:None):"""run a complete FTP session
default clean and transfer are no-ops don't delete if can't connect to server"""self.connectFtp()
cleanTarget()
transferAct()
self.connection.quit()if __name__ == '__main__':
ftp=FtpTools()
xfermode= 'download'
if len(sys.argv) > 1:
xfermode= sys.argv.pop(1)if xfermode == 'download':
ftp.configTransfer()#get+del 2nd arg
ftp.run(cleanTarget=ftp.cleanLocals, transferAct=ftp.downloadDir)elif xfermode == 'upload':
redir=os.path.basename((len(sys.argv) > 1 and sys.argv[1]) or '.')
ftp.configTransfer(site='192.168.30.252', rdir=redir, user='child')
ftp.run(cleanTarget=ftp.cleanRemotes, transferAct=ftp.uploadDir)else:print('Usage: ftptools.py ["download" | "upload"] [localdir]')