业务场景:
需求呢简单来说就是:服务A在B服务器上运行,而服务A主要是将某些文件下载并传输到C服务器上,但是服务A不能直接运行在C服务器上
所以就使用了ftplib,paramiko
下面是部分代码:
#! encoding=utf-8
from ftplib import FTP
import os
import sys
import time
import socket
import paramiko
import serverConfig
class MyFTP:
def __init__(self, host, port=21):
self.host = host
self.port = port
self.ftp = FTP()
# 重新设置下编码方式
self.ftp.encoding = 'utf-8'
self.log_file = open("log.txt", "a")
self.file_list = []
def login(self, username, password):
try:
timeout = 60
socket.setdefaulttimeout(timeout)
# 0主动模式 1 #被动模式
self.ftp.set_pasv(True)
# 打开调试级别2,显示详细信息
# self.ftp.set_debuglevel(2)
self.debug_print('----begin connect to %s' % self.host)
self.ftp.connect(self.host, self.port)
self.debug_print('------success connect to %s' % self.host)
self.debug_print('--------begin login to %s' % self.host)
self.ftp.login(username, password)
self.debug_print('-----------success login to %s' % self.host)
self.debug_print(self.ftp.welcome)
except Exception as err:
self.deal_error("FTP connect or login failed, error msg ->::%s" % err)
pass
def is_same_size(self, local_file, remote_file):
try:
remote_file_size = self.ftp.size(remote_file)
except Exception as err:
# self.debug_print("is_same_size() 错误描述为:%s" % err)
remote_file_size = -1
try:
local_file_size = os.path.getsize(local_file)
except Exception as err:
# self.debug_print("is_same_size() 错误描述为:%s" % err)
local_file_size = -1
self.debug_print('local_file_size:%d , remote_file_size:%d' % (local_file_size, remote_file_size))
if remote_file_size == local_file_size:
return 1
else:
return 0
def download_file(self, local_file, remote_file):
self.debug_print("download_file()---> local_path = %s ,remote_path = %s" % (local_file, remote_file))
if self.is_same_size(local_file, remote_file):
self.debug_print('%s 文件大小相同,无需下载' % local_file)
return
else:
try:
self.debug_print('>>>>>>>>>>>>下载文件 %s ... ...' % local_file)
buf_size = 1024
file_handler = open(local_file, 'wb')
self.ftp.retrbinary('RETR %s' % remote_file, file_handler.write, buf_size)
file_handler.close()
except Exception as err:
self.debug_print('下载文件出错,出现异常:%s ' % err)
return
def download_file_tree(self, local_path, remote_path):
print("download_file_tree()---> local_path = %s ,remote_path = %s" % (local_path, remote_path))
try:
self.ftp.cwd(remote_path)
except Exception as err:
self.debug_print('远程目录%s不存在,继续...' % remote_path + " ,具体错误描述为:%s" % err)
return
if not os.path.isdir(local_path):
self.debug_print('本地目录%s不存在,先创建本地目录' % local_path)
os.makedirs(local_path)
self.debug_print('切换至目录: %s' % self.ftp.pwd())
self.file_list = []
# 方法回调
self.ftp.dir(self.get_file_list)
remote_names = self.file_list
self.debug_print('远程目录 列表: %s' % remote_names)
for item in remote_names:
file_type = item[0]
file_name = item[1]
local = os.path.join(local_path, file_name)
if file_type == 'd':
print("download_file_tree()---> 下载目录: %s" % file_name)
self.download_file_tree(local, file_name)
elif file_type == '-':
print("download_file()---> 下载文件: %s" % file_name)
self.download_file(local, file_name)
self.ftp.cwd("..")
self.debug_print('返回上层目录 %s' % self.ftp.pwd())
return True
def upload_file(self, local_file, remote_file):
# if not os.path.isfile(local_file):
# self.debug_print('%s 不存在' % local_file)
# return
#
# if self.is_same_size(local_file, remote_file):
# self.debug_print('跳过相等的文件: %s' % local_file)
# return
buf_size = 1024
file_handler = open(local_file, 'rb')
self.ftp.storbinary('STOR %s' % remote_file, file_handler, buf_size)
file_handler.close()
self.debug_print('upload: %s' % local_file + "success!")
def mkdir(self, file_path):
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=serverConfig.IP, port=22, username=serverConfig.USER, password=serverConfig.PASSWD)
except Exception as e:
self.debug_print("mkdir need ssh connect, but failed, error msg: -> %s" % e)
else:
ssh.exec_command('mkdir -p %s'% file_path)
ssh.exec_command("chmod 777 %s" % file_path)
def close(self):
""" 退出ftp
"""
self.debug_print("close()---> FTP logout success")
self.ftp.quit()
self.log_file.close()
def debug_print(self, s):
self.write_log(s)
def deal_error(self, e):
log_str = '发生错误: %s' % e
self.write_log(log_str)
sys.exit()
def write_log(self, log_str):
time_now = time.localtime()
date_now = time.strftime('%Y-%m-%d', time_now)
format_log_str = "%s ---> %s \n " % (date_now, log_str)
print(format_log_str)
self.log_file.write(format_log_str)
if __name__ == "__main__":
my_ftp = MyFTP("xx.xx.xx.xx")
my_ftp.login("ftp用户名", "ftp用户密码")
# 下载单个文件
# my_ftp.download_file("G:/ftp_test/XTCLauncher.apk", "/App/AutoUpload/ouyangpeng/I12/Release/XTCLauncher.apk")
# 下载目录
# my_ftp.download_file_tree("G:/ftp_test/", "App/AutoUpload/ouyangpeng/I12/")
# 上传单个文件
my_ftp.upload_file(r"C:\Users\ysten\Desktop\Ocean\pythonSpiders\test.jpg", r"/app/test.jpg")
# 上传目录
# my_ftp.upload_file_tree("G:/ftp_test/", "/App/AutoUpload/ouyangpeng/I12/")
my_ftp.mkdir("/app/app")
my_ftp.close()
以上代码主要实现了传输的功能,在我实现了功能以后找了两台服务器进行测试,测试过程中还是比较顺利的,能够正常实现,但是当放到我们线上后,莫名的就开始报错了。。。。。
下面直接说引起这个错误的原因是什么?
因为我测试的时候没有指定ftp用户目录,默认是“/”,而我的业务逻辑就是从“/”根目录开始,动态创建多层目录,然后将其保存。
然而,运维将ftp用户的目录指定到了其他的目录,所以我的代码就找不到路径了,就报了上面那个错
本文讲述了在FTP服务中,通过ftplib和paramiko实现文件下载与上传时,如何处理业务场景中从根目录动态创建多层目录的问题,以及遇到的因FTP用户目录变更导致的路径错误解决方案。
1437

被折叠的 条评论
为什么被折叠?



