python 操作FTP

 封装FTP操作类

#coding:utf-8
__author__ = 'similarface'

import os, sys, ftplib
from getpass import getpass
from mimetypes import guess_type, add_type
dfltSite = '192.168.30.252'
dfltRdir = '.'
dfltUser = 'child'

class FtpTools:
    # allow these 3 to be redefined
    def getlocaldir(self):
        return (len(sys.argv) > 1 and sys.argv[1]) or '.'


    def getcleanall(self):
        #return raw_input('Clean target dir first?')[:1] in ['y','Y']
        return False

    def getpassword(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 == None

    def connectFtp(self):
        print('connecting...')
        connection = ftplib.FTP(self.remotesite)
        connection.login(self.remoteuser, self.remotepass)
        try:
            connection.cwd(self.remotedir)
        except Exception,e:
            print e
            connection.mkd(self.remotedir)
            connection.cwd(self.remotedir)
        if self.nonpassive:
            connection.set_pasv(False)
        self.connection = connection


    def cleanLocals(self):
        """
        尝试删除所有的本地文件
        """
        if self.cleanall:
            # 本地文件的遍历
            for localname in os.listdir(self.localdir):
                try:
                    # 本地文件删除
                    print('deleting local', localname)
                    os.remove(os.path.join(self.localdir, localname))
                except:
                    print('cannot delete local', localname)



    def cleanRemotes(self):
        """
        尝试删除所有远程文件为移除无效文件
        """
        if self.cleanall:
            for remotename in self.connection.nlst():
                try:
                    print('deleting remote', remotename)
                    self.connection.delete(remotename)
                except:
                    # remote dir listing # remote file delete
                    print('cannot delete remote', remotename)

    def downloadOne(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:本地文件
        """
        if self.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()

    def uploadOne(self, localname, localpath, remotename):
        """
        upload one file by FTP in text or binary mode remote name need not be same as local name
        使用FTP上传一个文件
        """
        if self.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()

    def downloadDir(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 in remotefiles:
            if remotename in ('.', '..'): continue
            localpath = os.path.join(self.localdir, remotename)
            #print('downloading', remotename, 'to', localpath, 'as', end=' ')
            self.downloadOne(remotename, localpath)
        print('Done:', len(remotefiles), 'files downloaded.')

    def uploadDir(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 in localfiles:
            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]')

 

posted @ 2016-01-21 16:57  similarface  阅读(1458)  评论(0编辑  收藏  举报