python中对于sftp与ftp的支持较少,很多方法都没有,如makedirs与exists检查,只能自己造轮子了,废话不多说,直接上代码。
import paramiko import os import time class SFTP_obj(): def action_try(fun): def wrapper(*args, **kwargs): # def 与 return 之后的函数名称一致 try: ret = fun(*args, **kwargs) return ret # return ret 与 ret=func(*args,**kwargs)一致 except Exception as error: print(‘函数 ‘ + fun.__name__ + ‘ 操作失败‘,end=‘ ‘) print(error) #print(traceback.print_exc()) #print(‘函数‘+fun.__name__+‘操作失败‘) return wrapper def __init__(self, host, username, password): self.host = host self.username = username self.password = password self.connect() def connect(self): ssh = paramiko.SSHClient() # automatically add keys without requiring human intervention ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(self.host, username=self.username, password=self.password) tr = ssh.get_transport() tr.default_max_packet_size = 100000000 tr.default_window_size = 100000000 self.sftp = ssh.open_sftp() time.sleep(1) print(‘open connect‘) def close(self): self.sftp.close() time.sleep(2) print(‘close connect‘) # 下载文件 @action_try def downloadfile(self,remotepath, localpath): self.sftp.close() self.connect() print(‘开始下载 ‘+ remotepath) try: self.sftp.get(remotepath,localpath) print(‘下载文件 ‘ + remotepath + ‘成功‘) return ‘1‘ except: print(‘下载文件 ‘ + remotepath + ‘失败‘) if os.path.exists(localpath): os.remove(localpath) return ‘0‘ finally: self.close() # list文件夹 @action_try def listdir(self, remotepath): path_list=[] list=self.sftp.listdir(remotepath) for name in list: path_list.append(os.path.join(remotepath,name)) return path_list # 递归遍历得到当前目录下所有的文件路径 @action_try def get_filepaths(self, remotepath,dir_paths=[],file_paths=[]): path_list = self.listdir(remotepath) for path in path_list: #判断是否为文件 if ‘d‘ not in str(self.sftp.lstat(path)).split()[0]: file_paths.append(path) #如果为文件夹 else: dir_paths.append(path) self.get_filepaths(path,dir_paths,file_paths) return dir_paths,file_paths #同步更新sftp,遍历下载文件到本地,同时创建与sftp相同的文件夹目录 @action_try def downloadfilelist(self,remotepath): upnumber = 0 dirslist, fileslist = self.get_filepaths(remotepath) all_path = dirslist + fileslist uplist = [] for path in all_path: localpath = os.path.join(‘./test‘, path.strip(‘/‘)) if not os.path.exists(localpath): uplist.append(localpath) print(‘本次需要更新 ‘ + str(len(uplist)) + ‘ 个文件‘) for dir in dirslist: #print(dir) localpath = os.path.join(‘./test‘, dir.strip(‘/‘)) if not os.path.exists(localpath): os.makedirs(localpath) upnumber = upnumber + 1 else: pass print(‘目录 ‘ + dir + ‘ 已存在,跳过下载‘) for file in fileslist: #print(file) localpath = os.path.join(‘./test‘, file.strip(‘/‘)) if not os.path.exists(localpath): if not os.path.exists(os.path.dirname(localpath)): os.makedirs(os.path.dirname(localpath)) flag=self.downloadfile(file, localpath) #假文件 # os.mknod(localpath) if flag==‘1‘: upnumber = upnumber + 1 else: pass print(‘文件 ‘ + file + ‘ 已存在,跳过下载‘) print(‘************************************‘) print(‘更新 ‘ + remotepath + ‘ 成功‘) print(‘本次更新了 ‘ + str(upnumber) + ‘ 个文件‘) print(‘************************************‘) if __name__=="__main__": host = ‘xxxx‘ username = ‘xxxx‘ password = ‘xxxx‘ s=SFTP_obj(host,username,password)
#-*- coding:utf-8 -*- import ftplib from ftplib import FTP import traceback import os class FTP_obj(): def action_try(fun): def wrapper(*args, **kwargs): # def 与 return 之后的函数名称一致 try: ret = fun(*args, **kwargs) return ret # return ret 与 ret=func(*args,**kwargs)一致 except Exception as error: print(‘函数‘ + fun.__name__ + ‘操作失败‘,end=‘ ‘) print(error) #print(traceback.print_exc()) #print(‘函数‘+fun.__name__+‘操作失败‘) return wrapper def __init__(self,host,username,password): self.ftp = FTP() # ftp.set_debuglevel(2) #打开调试级别2,显示详细信息 self.ftp.connect(host, 21) # 连接 self.ftp.login(username, password) # 登录,如果匿名登录则用空串代替即可 # 下载文件 @action_try def downloadfile(self,remotepath, localpath): bufsize = 1024 # 设置缓冲块大小 fp = open(localpath, ‘wb‘) # 以写模式在本地打开文件 self.ftp.retrbinary(‘RETR ‘ + remotepath, fp.write, bufsize) # 接收服务器上文件并写入本地文件 self.ftp.set_debuglevel(0) # 关闭调试 print(‘下载文件‘ + remotepath + ‘成功‘) fp.close() # 关闭文件 #上传文件 @action_try def uploadfile(self,remotepath, localpath): bufsize = 1024 fp = open(localpath, ‘rb‘) self.ftp.storbinary(‘STOR ‘ + remotepath, fp, bufsize) # 上传文件 self.ftp.set_debuglevel(0) print(‘上传文件‘ + remotepath + ‘成功‘) fp.close() #删除文件 @action_try def delete(self,remotepath): self.ftp.delete(remotepath) print(‘删除文件‘ + remotepath + ‘成功‘) #创建文件夹 def mkdir(self,remotepath): self.ftp.mkd(remotepath) print(‘创建文件夹‘ + remotepath + ‘成功‘) # 删除文件夹 @action_try def dldir(self, remotepath): self.ftp.rmd(remotepath) print(‘删除文件夹‘ + remotepath + ‘成功‘) #list文件夹 @action_try def listdir(self, remotepath): list = self.ftp.nlst(remotepath) return list #得到本地需要更新的所有文件路径 def get_local_paths(self,local,dir_paths=[],file_paths=[]): path_list = os.listdir(local) for path in path_list: path=os.path.join(local,path) # 判断是否为文件 if os.path.isfile(path): file_paths.append(path) # 如果为文件夹 else: dir_paths.append(path) self.get_local_paths(path, dir_paths, file_paths) return dir_paths, file_paths # 将本地目标文件夹所有内容全部上传ftp def upload_all_files(self,local): upnumber=0 dirslist, fileslist = self.get_local_paths(local) all_path = dirslist + fileslist uplist = [] for path in all_path: print(path) ftppath = os.path.join(‘/XXXX_image/‘, path.replace(‘/home/ts/下载/huilin_ftp/‘,‘‘)) if self.check(ftppath)==‘none‘: uplist.append(ftppath) print(‘本次需要更新 ‘ + str(len(uplist)) + ‘ 个文件‘) print(uplist) for dir in dirslist: #print(‘****‘+dir) ftppath = os.path.join(‘/XXXX_image/‘, dir.replace(‘/home/ts/下载/huilin_ftp/‘,‘‘)) self.makedirs(ftppath) for file in fileslist: #print(file) ftppath = os.path.join(‘/XXXX_image/‘, file.replace(‘/home/ts/下载/huilin_ftp/‘,‘‘)) ftp_dir=os.path.join(‘/XXXX_image/‘, os.path.dirname(file).replace(‘/home/ts/下载/huilin_ftp/‘,‘‘)) if self.check(ftppath) != ‘file_exists‘: if self.check(ftp_dir)!=‘dir_exists‘: self.makedirs(ftp_dir) self.uploadfile(ftppath,file) else: print(‘文件 ‘+file+‘ 已经存在,跳过上传‘) #判断路径类型以及是否存在 def check(self,path): type=‘none‘ try: self.ftp.size(path) type=‘file_exists‘ except: try: self.ftp.cwd(path) type=‘dir_exists‘ except: type=‘none‘ finally: return type #递归创建文件夹 def makedirs(self, path): if self.check(path)==‘dir_exists‘: print(‘文件夹 ‘+path+‘ 存在,跳过上传‘) else: path_split = path.strip(‘/‘).split(‘/‘) dir_path = ‘/‘ for item in path_split: dir_path = dir_path + ‘/‘ + item if self.check(path)!=‘dir_exists‘: try: self.mkdir(dir_path) except: pass if __name__ == "__main__": host=‘XXXX‘ username=‘XXXX‘ password=‘XXXX‘ ftp=FTP_obj(host,username,password)
原文:https://www.cnblogs.com/CYHISTW/p/14116030.html