"""使用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)