基於Paramiko的SFTP功能 -- 支持目錄夾get/put

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "hiki"
# Email: [email protected]

'''
paramiko -- sftp : get/put
'''

import os
import stat
import logging
import paramiko
from OPS import settings

class SftpHandler(object):
    def __init__(self, host, port, username):
        self.host = host
        self.port = port
        self.username = username
        self.key = settings.PKEY_FILE
        self.backdir = settings.BACK_DIR
        self.result = []

        try:
            paramiko.util.log_to_file(os.path.join(settings.PID_DIRS, "paramiko_sftp.log"))
            key = paramiko.RSAKey.from_private_key_file(self.key)
            self.t = paramiko.Transport((self.host, self.port))
            self.t.connect(username=self.username, pkey=key)
            self.sftp = paramiko.SFTPClient.from_transport(self.t)
        except Exception,e:
            print "out: ",e
            log = logging.getLogger('sftp_error')
            log.info('SFTP connection error from %s, %s.'%(self.host, e))

    def __del__(self):
        try:
            self.t.close()
            self.result = []
            # print "del self.t"
        except:
            pass

    def data_put(self, local_path, remote_path):
        try:
            if os.path.isfile(local_path):
                filename = local_path.split("/")[-1]
                remote_file = os.path.join(remote_path, filename)
                result = self.sftp.put(local_path, remote_file)
                # print result
                if result:
                    log = logging.getLogger('sftp_access')
                    log.info('SFTP put [%s --> %s] success to %s.' % (local_path, remote_file, self.host))
                    self.result.append('SFTP put [%s --> %s] success to %s.' % (local_path, remote_file, self.host))
                    return self.result
                else:
                    log = logging.getLogger('sftp_error')
                    log.info('SFTP put [%s --> %s] failed to %s, %s.' % (local_path, remote_file, self.host,result))
                    self.result.append('SFTP put [%s --> %s] failed to %s, %s.' % (local_path, remote_file, self.host,result))
                    return self.result
            elif os.path.isdir(local_path):
                # loop dir
                result = self.data_put_loop_dir(local_path, remote_path)
                return self.result
            else:
                log = logging.getLogger('sftp_error')
                log.info('Local_path ==> [%s] is not exist.' % local_path)
                self.result.append('Local_path ==> [%s] is not exist.' % local_path)
                return self.result

        except Exception,e:
            log = logging.getLogger('sftp_error')
            log.info('SFTP put error from %s, %s.'%(self.host, e))
            self.result.append('SFTP put error from %s, %s.'%(self.host, e))
            return self.result

    def data_put_loop_dir(self, local_path, remote_path):
        try:
            file_list = os.listdir(local_path)

            # Remote create dir if not exist
            dirname = local_path.split("/")[-1]
            mkdirname = os.path.join(remote_path, dirname)
            try:
                self.sftp.listdir_attr(mkdirname)
            except:
                result = self.sftp.mkdir(mkdirname)
                if result == None:
                    log = logging.getLogger("sftp_access")
                    log.info('Remote create dir[%s] succeed.' % mkdirname)
                else:
                    log = logging.getLogger("sftp_error")
                    log.info('Remote create dir[%s] failed, %s.' % (mkdirname, str(result)))
                    self.result.append('Remote create dir failed, %s.' % str(result))
                    return self.result

            # if create dir succeed, then start put file_list
            isfile_list = []
            isdir_list = []
            for filename in file_list:
                if os.path.isfile(os.path.join(local_path, filename)):
                    isfile_list.append(filename)
                elif os.path.isdir(os.path.join(local_path, filename)):
                    isdir_list.append(filename)
                else:
                    pass

            # first step: deal file
            for file_name in isfile_list:
                local_file = os.path.join(local_path, file_name)
                remote_file = os.path.join(mkdirname, file_name)
                result = self.sftp.put(local_file, remote_file)
                if result:
                    log = logging.getLogger('sftp_access')
                    log.info('SFTP put [%s --> %s] success to %s.' % (local_path, remote_file, self.host))
                    self.result.append('SFTP put [%s --> %s] success to %s.' % (local_path, remote_file, self.host))
                else:
                    log = logging.getLogger('sftp_error')
                    log.info('SFTP put [%s --> %s] failed to %s, %s.' % (local_path, remote_file, self.host, result))
                    self.result.append('SFTP put [%s --> %s] failed to %s, %s.' % (local_path, remote_file, self.host, result))

            # second step: loop dir
            n = 0
            for dir_name in isdir_list:
                if n > 0:
                    local_path = os.path.join(os.path.dirname(local_path), dir_name)
                else:
                    local_path = os.path.join(local_path, dir_name)
                remote_path = mkdirname
                self.data_put_loop_dir(local_path, remote_path)
                n += 1
            return self.result
        except Exception,e:
            log = logging.getLogger('sftp_error')
            log.info('SFTP put error, %s.' % e)
            self.result.append('SFTP put error, %s.' % e)
            return self.result

    def data_get(self, local_path, remote_path):
        try:
            # check remote_path type
            try:
                result = self.sftp.stat(remote_path)
                if result:
                    try:
                        self.sftp.listdir_attr(remote_path)
                        stdout, stderr = (['directory'],[])
                    except:
                        stdout, stderr = (['file'], [])
            except Exception,e:
                log = logging.getLogger('sftp_error')
                log.info('SFTP get [%s] error, %s.' % (remote_path, e))
                self.result.append('SFTP get [%s] error, %s.' % (remote_path,e))
                return self.result

            if len(stderr) == 0:
                # stdout = stdout[0].split("\n")[0]
                if 'file' in stdout:
                    filename = remote_path.split("/")[-1]
                    local_file = os.path.join(local_path, filename)
                    if os.path.isdir(local_path):
                        pass
                    else:
                        os.makedirs(local_path)

                    self.sftp.get(remote_path, local_file)
                    if os.path.isfile(local_file):
                        log = logging.getLogger('sftp_access')
                        log.info('SFTP get [%s --> %s] success to %s.' % (remote_path, local_file, self.host))
                        self.result.append('SFTP get [%s --> %s] success from %s.' % (remote_path, local_file, self.host))
                        return self.result
                    else:
                        log = logging.getLogger('sftp_error')
                        log.info('SFTP get [%s --> %s] failed to %s.' % (remote_path, local_file, self.host))
                        self.result.append('SFTP get [%s --> %s] failed from %s, %s not exit.' % (remote_path, local_file, self.host, local_file))
                        return self.result
                elif 'directory' in stdout:

                    result = self.data_get_loop_dir(local_path, remote_path)
                    return self.result

                else:
                    return self.result

        except Exception,e:
            log = logging.getLogger('sftp_error')
            log.info('SFTP get error, %s.' % e)
            self.result.append('SFTP get error, %s.' % e)
            return self.result

    def data_get_loop_dir(self, local_path, remote_path):
        try:
            if os.path.isdir(local_path):
                pass
            else:
                os.makedirs(local_path)

            # check file/dir
            isfile_list = []
            isdir_list = []
            remote_allfiles = self.sftp.listdir_attr(remote_path)
            for f in remote_allfiles:
                remote_file = os.path.join(remote_path, f.filename)
                dirname = remote_path.split("/")[-1]
                local_file = os.path.join(os.path.join(local_path,dirname), f.filename)
                if stat.S_ISDIR(f.st_mode):
                    isdir_list.append(remote_file)
                else:
                    isfile_list.append(remote_file)

            # first step: get file
            for file_name in isfile_list:
                remote_file = file_name
                try:
                    os.makedirs(os.path.join(local_path,file_name.split("/")[-2]))
                except:
                    pass
                local_file = os.path.join(local_path,os.path.join(file_name.split("/")[-2], file_name.split("/")[-1]))
                self.sftp.get(remote_file, local_file)
                if os.path.isfile(local_file):
                    log = logging.getLogger('sftp_access')
                    log.info('SFTP get [%s --> %s] success to %s.' % (remote_file, local_file, self.host))
                    self.result.append('SFTP get [%s --> %s] success from %s.' % (remote_file, local_file, self.host))
                else:
                    log = logging.getLogger('sftp_error')
                    log.info('SFTP get [%s --> %s] failed to %s.' % (remote_file, local_file, self.host))
                    self.result.append('SFTP get [%s --> %s] failed from %s, %s not exit.' % (remote_file, local_file, self.host, local_file))

            # second step: loop dir
            n = 0
            for dir_name in isdir_list:
                if n > 0:
                    local_path = local_path
                else:
                    local_path = os.path.join(local_path, dir_name.split("/")[-2])
                remote_path = dir_name
                self.data_get_loop_dir(local_path, remote_path)
                n += 1

            return self.result
        except Exception,e:
            log = logging.getLogger('sftp_error')
            log.info('SFTP get error, %s.' % e)
            self.result.append('SFTP get error, %s.' % e)
            return self.result
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章