zoukankan      html  css  js  c++  java
  • paramiko批量上传下载sftp,解决访问windows系列sftp乱码问题

    一、封装代码

    import os
    import paramiko
    from stat import S_ISDIR
    import shutil
    
    
    class ConnectSftp(object):
        def __init__(self,ip,port,username,password):
            self.ip=ip
            self.port=port
            self.username=username
            self.password=password
            self.connect()
    
        def connect(self):
            self.transport = paramiko.Transport((self.ip, self.port))
            self.transport.connect(username=self.username, password=self.password)
            self.sftp = paramiko.SFTPClient.from_transport(self.transport)
    
        def close(self):
            self.transport.close()
    
        def isdir(self,path):
            try:
                return S_ISDIR(self.sftp.stat(path).st_mode)
            except IOError:
                return False
    
        def sftp_rm(self,path):
            files = self.sftp.listdir(path=path)
            for f in files:
                filepath = os.path.join(path, f)
                if self.isdir(filepath):
                    self.sftp_rm(filepath)
                else:
                    self.sftp.remove(filepath)
            self.sftp.rmdir(path)
    
        def local_to_sftp(self,local_dir_name,remote_dir_name,move_state=False):
            '''
            :param local_dir_name: 本地文件夹路径
            :param remote_dir_name: sftp文件夹路径
            :param move_state: 是否删除本地文件夹
            :return:
            '''
            if os.path.isdir(local_dir_name):
                # 文件夹,不能直接下载,需要继续循环
                self.check_sftp_dir(remote_dir_name)
                for remote_file_name in os.listdir(local_dir_name):
                    sub_local = os.path.join(local_dir_name, remote_file_name)
                    sub_local = sub_local.replace('\', '/')
                    sub_remote = os.path.join(remote_dir_name, remote_file_name)
                    sub_remote = sub_remote.replace('\', '/')
                    print(sub_local, sub_remote)
                    self.local_to_sftp(sub_local, sub_remote)
            else:
                # 文件,直接上传
                print('开始上传文件:' + local_dir_name)
                self.sftp.put(local_dir_name, remote_dir_name)
            if move_state:
                shutil.rmtree(local_dir_name)
    
        def sftp_to_local(self,remote_dir_name,local_dir_name,move_state=False):
            '''
            :param remote_dir_name: sftp文件夹路径
            :param local_dir_name: 本地文件夹路径
            :param move_state: 是否删除sftp文件夹
            :return:
            '''
            try:
                self.sftp.stat(remote_dir_name)
            except Exception:
                raise BaseException({"error":"sftp路径不存在"})
            remote_file = self.sftp.stat(remote_dir_name)
            if S_ISDIR(remote_file.st_mode):
                # 文件夹,不能直接下载,需要继续循环
                self.check_local_dir(local_dir_name)
                print('开始下载文件夹:' + remote_dir_name)
                for remote_file_name in self.sftp.listdir(remote_dir_name):
                    sub_remote = os.path.join(remote_dir_name, remote_file_name)
                    sub_remote = sub_remote.replace('\', '/')
                    sub_local = os.path.join(local_dir_name, remote_file_name)
                    sub_local = sub_local.replace('\', '/')
                    self.sftp_to_local(sub_remote, sub_local)
            else:
                # 文件,直接下载
                print('开始下载文件:' + remote_dir_name)
                self.sftp.get(remote_dir_name, local_dir_name)
            if move_state:
                self.sftp_rm(remote_dir_name)
    
    
        def check_local_dir(self, local_dir_name):
            """本地文件夹是否存在,不存在则创建"""
            if not os.path.exists(local_dir_name):
                os.makedirs(local_dir_name)
    
        def check_sftp_dir(self, remote_dir_name):
            """sftp文件夹是否存在,不存在则创建"""
            try:
                self.sftp.stat(remote_dir_name)
            except IOError as e:
                self.sftp.mkdir(remote_dir_name)
    
        def cmd(self, command):
            ssh = paramiko.SSHClient()
            ssh._transport = self.transport
            stdin, stdout, stderr = ssh.exec_command(command)
            print(stdout)
            result = stdout.read()
            return result
    
    
    cs=ConnectSftp('ip',port,'name','pwd')
    if __name__ == '__main__':
        cs.local_to_sftp(r"本地路径",'sftp路径',move_state=True)
        cs.sftp_to_local("sftp路径",r"本地路径",move_state=True)
        cs.close()

    二、解决windows2008-sftp文件路径乱码

    找到paramiko下的py3compat文件,将以下4个函数内的编码改成‘gbk’

        def b(s, encoding="gbk"):
            """cast unicode or bytes to bytes"""
            if isinstance(s, bytes):
                return s
            elif isinstance(s, str):
                return s.encode(encoding)
            else:
                raise TypeError("Expected unicode or bytes, got {!r}".format(s))
    
        def u(s, encoding="gbk"):
            """cast bytes or unicode to unicode"""
            if isinstance(s, bytes):
                return s.decode(encoding)
            elif isinstance(s, str):
                return s
            else:
                raise TypeError("Expected unicode or bytes, got {!r}".format(s))

    def b(s, encoding="gbk"): # NOQA """cast unicode or bytes to bytes""" if isinstance(s, str): return s elif isinstance(s, unicode): # NOQA return s.encode(encoding) elif isinstance(s, buffer): # NOQA return s else: raise TypeError("Expected unicode or bytes, got {!r}".format(s)) def u(s, encoding="gbk"): # NOQA """cast bytes or unicode to unicode""" if isinstance(s, str): return s.decode(encoding) elif isinstance(s, unicode): # NOQA return s elif isinstance(s, buffer): # NOQA return s.decode(encoding) else: raise TypeError("Expected unicode or bytes, got {!r}".format(s))
  • 相关阅读:
    快速幂模板
    部分有关素数的题
    POJ 3624 Charm Bracelet (01背包)
    51Nod 1085 背包问题 (01背包)
    POJ 1789 Truck History (Kruskal 最小生成树)
    HDU 1996 汉诺塔VI
    HDU 2511 汉诺塔X
    HDU 2175 汉诺塔IX (递推)
    HDU 2077 汉诺塔IV (递推)
    HDU 2064 汉诺塔III (递推)
  • 原文地址:https://www.cnblogs.com/angelyan/p/12670444.html
Copyright © 2011-2022 走看看