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))
  • 相关阅读:
    docker使用
    解决wps linux中文字体名字全是英文
    解决小程序云函数操作数据库回调不执行
    解决XP“不是有效Win32程序” 不是改Platform toolset
    [hdu1686] Oulipo【KMP】
    [poj 2104] K-th Number【主席树】
    bzoj2806 [Apio2012]dispatching【可并堆】
    bzoj1492 [NOI2007]货币兑换Cash【cdq分治】
    [coci2015-2016 coii] torrent【树形dp 二分】
    [coci2015-2016 coii] Palinilap【字符串 哈希】
  • 原文地址:https://www.cnblogs.com/angelyan/p/12670444.html
Copyright © 2011-2022 走看看