1. 程式人生 > >sftp下載 上傳

sftp下載 上傳

"""使用paramiko模組中的sftp登陸遠端主機,實現上傳和下載功能"""

# 根據輸入引數判斷是檔案還是目錄,進行上傳和下載
# 本地引數local需要與遠端引數remote型別一致,檔案以檔名結尾,目錄以\結尾
# 上傳和下載的本地和遠端目錄需要存在
# 異常捕獲


import paramiko
import os
import logging
from stat import S_ISDIR as isdir
import re

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')


class Sftp(object):

    def __init__(self, ip, username, password):
        self.ip = ip
        self.username = username
        self.password = password
        self.sftp = self.connect()

    def connect(self):
        try:
            t = paramiko.Transport((self.ip, 22))  # 建立連線
            # logging.info(self.ip)

            t.connect(username=self.username, password=self.password)
            sftp = paramiko.SFTPClient.from_transport(t)
            return sftp
            # logging.info(self.sftp)
            # return sftp
        except Exception as e:
            logging.info(e)

    # # 獲取單個檔案
    # def get(self, remotefile, localfile):
    #
    #     self.sftp.get(remotefile, localfile)
    #
    # # 上傳單個檔案
    # def put(self, localfile, remotefile):
    #
    #     self.sftp.put(localfile, remotefile)

    # 獲取目錄 所有檔案
    def __get_all_file(self, remote_dir):
        all_files = list()

        # 去掉路徑字串最後的字元'/',如果有的話
        if remote_dir[-1] == '/':
            remote_dir = remote_dir[0:-1]

        # 獲取當前指定目錄下的所有目錄及檔案,包含屬性值
        # logging.info(sftp)
        files = self.sftp.listdir_attr(remote_dir)

        for i in files:
            # 如果是檔案 remote_dir目錄中的完整路徑
            filename = remote_dir + '/' + i.filename
            # logging.info(filename)
            # 如果是目錄,遞迴處理該目錄
            if isdir(i.st_mode):
                if not os.path.exists(i.filename):
                    os.makedirs(i.filename)
                all_files.extend(self.__get_all_file(filename))
            else:
                all_files.append(filename)

        return all_files

    def get_dir(self, remote_dir, local_dir):
            all_files = self.__get_all_file(remote_dir)
            for x in all_files:

                filepath = re.split('[:/]', x)
                filename = filepath[-1]
                local_path = local_dir + os.sep + '/'.join(filepath[1:-1])
                if not os.path.exists(local_path):
                    os.makedirs(local_path)
                local_filename = os.path.join(local_path, filename)
                print(u'get檔案{}傳輸中'.format(filename))
                # logging.info(sftp)
                self.sftp.get(x, local_filename)

    def __put_all_file(self, local_dir):
        # 儲存所有檔案的列表
        all_files = list()
        # 獲取當前指定目錄下的所有目錄及檔案 或目錄的完整路徑
        files = os.listdir(local_dir)
        for i in files:
            # local_dir目錄中每一個檔案或目錄的完整路徑
            filename = os.path.join(local_dir, i)
            # 是目錄就遞迴處理
            if os.path.isdir(i):
                all_files.extend(self.__put_all_file(filename))
            else:
                all_files.append(filename)

        return all_files

    def put_dir(self, local_dir, remote_dir):
        # 去掉字串最後的字元
        if remote_dir[-1] == '/':
            remote_dir = remote_dir[0:-1]
        # 獲取本地指定的目錄及目錄下的檔案
        all_files = self.__put_all_file(local_dir)
        for i in all_files:
            filename = os.path.split(i)[-1]
            remote_filename = remote_dir + '/' + filename
            print(u'Put檔案{}傳輸中...'.format(filename))
            self.sftp.put(i, remote_filename)


if __name__ == '__main__':

    remote_path = '/upload'
    local_path = '/home/python/Desktop/'
    host = Sftp('47.104.236.156', 'test', 'test123')
    # 將遠端remote_path目錄中的所有檔案get到本地local_path目錄
    host.get_dir(remote_path, local_path)
    # host.put_dir(local_path, remote_path)