2021.1.8更新

下面的方法在传输速率有差异的情况下,会出现丢包的情况,导致数据不完整,现在用另一种更为简单的方式,能保证数据的正确性

def ftp(file_name, data_path):with ftputil.FTPHost(host=etl_config.FtpHost, user=etl_config.FtpUser, passwd=etl_config.FtpPwd) as host:local_filename = local_path + file_name# 如果FTP上不存在待下载的文件,需要返回报错if not os.path.exists(local_filename):# 判断本地是否存在文件,不存在则下载try:host.download(data_path, local_filename)print('File Download Success!')except ftplib.error_perm:print('File Error!')os.unlink(data_path)else:print('File Exist!')

1.启动ftp服务

# -*- coding:utf-8 -*-
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer# 实例化DummyAuthorizer来创建ftp用户
authorizer = DummyAuthorizer()
# 参数:用户名,密码,目录,权限
authorizer.add_user('admin', '123456', r'E:\ftp_test', perm='elradfmwMT')
# 匿名登录
# authorizer.add_anonymous('/home/nobody')
handler = FTPHandler
handler.authorizer = authorizer
# 参数:IP,端口,handler
server = FTPServer(('127.0.0.1', 21), handler)  # 设置为0.0.0.0为本机的IP地址
server.serve_forever()

在浏览器输入ftp://localhost/

2.客户端1

#!/usr/bin/python
# -*- coding: UTF-8 -*-from ftplib import FTP
import os
import sys
import time
import socketclass MyFTP:"""ftp自动下载、自动上传脚本,可以递归目录操作作者:欧阳鹏博客地址:http://blog.csdn.net/ouyang_peng/article/details/79271113"""def __init__(self, host, port=21):""" 初始化 FTP 客户端参数:host:ip地址port:端口号"""# print("__init__()---> host = %s ,port = %s" % (host, port))self.host = hostself.port = portself.ftp = FTP()# 重新设置下编码方式self.ftp.encoding = 'gbk'self.log_file = open("log.txt", "a")self.file_list = []def login(self, username, password):""" 初始化 FTP 客户端参数:username: 用户名password: 密码"""try:timeout = 60socket.setdefaulttimeout(timeout)# 0主动模式 1 #被动模式self.ftp.set_pasv(True)# 打开调试级别2,显示详细信息self.ftp.set_debuglevel(2)self.debug_print('开始尝试连接到 %s' % self.host)self.ftp.connect(self.host, self.port)self.debug_print('成功连接到 %s' % self.host)self.debug_print('开始尝试登录到 %s' % self.host)self.ftp.login(username, password)self.debug_print('成功登录到 %s' % self.host)self.debug_print(self.ftp.welcome)except Exception as err:self.deal_error("FTP 连接或登录失败 ,错误描述为:%s" % err)passdef is_same_size(self, local_file, remote_file):"""判断远程文件和本地文件大小是否一致参数: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 = -1try:local_file_size = os.path.getsize(local_file)except Exception as err:# self.debug_print("is_same_size() 错误描述为:%s" % err)local_file_size = -1self.debug_print('local_file_size:%d  , remote_file_size:%d' % (local_file_size, remote_file_size))if remote_file_size == local_file_size:return 1else:return 0def download_file(self, local_file, remote_file):"""从ftp下载文件参数: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)returnelse:try:self.debug_print('>>>>>>>>>>>>下载文件 %s ... ...' % local_file)buf_size = 1024file_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)returndef download_file_tree(self, local_path, remote_path):"""从远程目录下载多个文件到本地目录参数: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)returnif 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_listself.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 Truedef upload_file(self, local_file, remote_file):"""从本地上传文件到ftp参数:local_path: 本地文件remote_path: 远程文件"""if not os.path.isfile(local_file):self.debug_print('%s 不存在' % local_file)returnif self.is_same_size(local_file, remote_file):self.debug_print('跳过相等的文件: %s' % local_file)returnbuf_size = 1024file_handler = open(local_file, 'rb')self.ftp.storbinary('STOR %s' % remote_file, file_handler, buf_size)file_handler.close()self.debug_print('上传: %s' % local_file + "成功!")def upload_file_tree(self, local_path, remote_path):"""从本地上传目录下多个文件到ftp参数:local_path: 本地路径remote_path: 远程路径"""if not os.path.isdir(local_path):self.debug_print('本地目录 %s 不存在' % local_path)returnself.ftp.cwd(remote_path)self.debug_print('切换至远程目录: %s' % self.ftp.pwd())local_name_list = os.listdir(local_path)for local_name in local_name_list:src = os.path.join(local_path, local_name)if os.path.isdir(src):try:self.ftp.mkd(local_name)except Exception as err:self.debug_print("目录已存在 %s ,具体错误描述为:%s" % (local_name, err))self.debug_print("upload_file_tree()---> 上传目录: %s" % local_name)self.upload_file_tree(src, local_name)else:self.debug_print("upload_file_tree()---> 上传文件: %s" % local_name)self.upload_file(src, local_name)self.ftp.cwd("..")def close(self):""" 退出ftp"""self.debug_print("close()---> FTP退出")self.ftp.quit()self.log_file.close()def debug_print(self, s):""" 打印日志"""self.write_log(s)def deal_error(self, e):""" 处理错误异常参数:e:异常"""log_str = '发生错误: %s' % eself.write_log(log_str)sys.exit()def write_log(self, log_str):""" 记录日志参数: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)def get_file_list(self, line):""" 获取文件列表参数:line:"""file_arr = self.get_file_name(line)# 去除  . 和  ..if file_arr[1] not in ['.', '..']:self.file_list.append(file_arr)def get_file_name(self, line):""" 获取文件名参数:line:"""pos = line.rfind(':')while (line[pos] != ' '):pos += 1while (line[pos] == ' '):pos += 1file_arr = [line[0], line[pos:]]return file_arrif __name__ == "__main__":my_ftp = MyFTP("127.0.0.1")my_ftp.login("admin", "123456")# 下载单个文件,第一个本地和服务器下一样文件类型的空文件,第二个是ftp服务器上要下载到本地的路径文件# my_ftp.download_file("E:/ftp_test/download_test/6.txt", "/download/test.txt")# 下载目录# my_ftp.download_file_tree("E:/ftp_test/", "App/AutoUpload/ouyangpeng/I12/")# 上传单个文件 第一个是本地文件,第二个是ftp服务器下的路径,不加前面的根路径名,不用创建空文件,起一个上传后的名字my_ftp.upload_file("E:/ftp_test/upload/upload_test.txt", "/upload_test/1.txt")# 上传单个文件# my_ftp.upload_file("G:/ftp_test/Release/XTCLauncher.apk", "/App/AutoUpload/ouyangpeng/I12/Release/XTCLauncher.apk")# 上传目录# my_ftp.upload_file_tree("E:/ftp_test/upload_test/", "/ftp_test/upload/")# my_ftp.upload_file_tree("E:/ftp_test/upload/upload_test.txt", "/ftp_test/")my_ftp.close()

3.客户端2

# -*- coding: utf-8 -*-
from ftplib import FTP
import time, tarfile, os# 连接ftp
def ftpconnect(host, port, username, password):ftp = FTP()# 打开调试级别2,显示详细信息# ftp.set_debuglevel(2)ftp.connect(host, port)ftp.login(username, password)return ftp# 从ftp下载文件
def downloadfile(ftp, remotepath, localpath):# 设置的缓冲区大小bufsize = 1024fp = open(localpath, 'wb')ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)ftp.set_debuglevel(0)  # 参数为0,关闭调试模式fp.close()# 从本地上传文件到ftp
def uploadfile(ftp, remotepath, localpath):bufsize = 1024fp = open(localpath, 'rb')ftp.storbinary('STOR ' + remotepath, fp, bufsize)ftp.set_debuglevel(0)fp.close()if __name__ == "__main__":# host,port, username, passwordftp = ftpconnect("127.0.0.1", 21, "admin", "123456")# 下载文件,第一个是ftp服务器路径下的文件,第二个是要下载到本地的路径文件downloadfile(ftp, "/test.txt", r"E:\ftp_test\download\test.txt")# 上传文件,第一个是要上传到ftp服务器路径下的文件,第二个是本地要上传的的路径文件uploadfile(ftp, '/upload/1.txt', "E:/ftp_test/upload/upload_test.txt")# ftp.close() #关闭ftp# #调用本地播放器播放下载的视频# os.system('start D:\soft\kugou\KGMusic\KuGou.exe C:\Users\Administrator\Desktop\ftp\test.mp3')print(ftp.getwelcome())  # 打印出欢迎信息# 获取当前路径pwd_path = ftp.pwd()print("FTP当前路径:", pwd_path)# 显示目录下所有目录信息# ftp.dir()# 设置FTP当前操作的路径ftp.cwd('/upload/')# 返回一个文件名列表filename_list = ftp.nlst()print(filename_list)ftp.mkd('目录名')  # 新建远程目录ftp.rmd('目录名')  # 删除远程目录ftp.delete('文件名')  # 删除远程文件ftp.rename('fromname', 'toname')  # 将fromname修改名称为toname# 逐行读取ftp文本文件file = '/upload/upload_test.txt'# ftp.retrlines('RETR %s' % file)# 与 retrlines()类似,只是这个指令处理二进制文件。回调函数 cb 用于处理每一块(块大小默认为 8KB)下载的数据# ftp.retrbinary('RETR %s' % file)

本地文件路径

只是简单的实现本地的ftp服务的测试,没有在具体的使用

参考链接

https://www.cnblogs.com/xiao-apple36/p/9415237.html

https://blog.csdn.net/ouyang_peng/article/details/79271113

https://www.cnblogs.com/huzixia/p/10389945.html#label1

python 实现FTP上传下载文件相关推荐

  1. python get 下载 目录_python实现支持目录FTP上传下载文件的方法

    本文实例讲述了python实现支持目录FTP上传下载文件的方法.分享给大家供大家参考.具体如下: 该程序支持ftp上传下载文件和目录.适用于windows和linux平台. #!/usr/bin/en ...

  2. python上传本地文件到ftp_python实现的简单FTP上传下载文件实例

    本文实例讲述了python实现的简单FTP上传下载文件的方法.分享给大家供大家参考.具体如下: python本身自带一个FTP模块,可以实现上传下载的函数功能. #!/usr/bin/env pyth ...

  3. android ftp同步程序,ftp同步 安卓,安卓手机ftp上传下载文件功能同步视频照片

    手机拍照越来方便,手机里的照片也越积越多,手机运行缓慢,本文利用安卓的每步FTP服务APP来自动实现手机视频照片的同步,释放手机被占用的存储空间.在机顶盒上运行每步FTP服务,机顶盒USB口连接U盘做 ...

  4. bat定时进行ftp上传下载文件

    bat进行ftp上传下载文件 参考文章: https://blog.csdn.net/yongzai666/article/details/86488761 背景: 由于公司某个系统原本硬盘损坏 , ...

  5. ftp上传-下载文件通用工具类,已实测

    话不多说直接上代码 package com.springboot.demo.utils;import lombok.extern.slf4j.Slf4j; import org.apache.comm ...

  6. java ftp上传文件_jaVA使用FTP上传下载文件的问题

    为了实现 FTP上传下载,大概试了两个方法 sun.net.ftp.FtpClient org.apache.commons.net 一开始使用sun.net.ftp.FtpClient,结果发现唯一 ...

  7. ftp上传下载文件详解

    首先导入包 import org.apache.commons.NET.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; FTPCli ...

  8. python ftp上传/下载文件,带进度条显示

    文章目录 想法 最终效果 python代码 补充:下载带进度显示 想法 用python写个ftp上传文件的功能,想要实时看到上传进度,进度条ui部分,使用python的tkinter库实现. 最终效果 ...

  9. ftp: connect: 没有到主机的路由_Qt之FTP上传/下载文件操作

    ​一个简单的Ftp客户端文件上传/下载操作示例. 上传文件 QNetworkAccessManager manager; QUrl url; /* 设置通讯协议 */ url.setScheme(&q ...

最新文章

  1. 前端进阶(三) webpack处理vue以及vue-cli脚手架环境
  2. 小波变换学习~语音端点检测
  3. On branch master nothing to commit, working tree clean
  4. oracle添加文件,ORACLE---添加控制文件
  5. 1.5编程基础之循环控制 03 均值 python
  6. 已获千赞,从理论到实践!
  7. 小程序小程序--定时器(定时任务、循环任务)
  8. DDOS防火墙新一代操作思路与进阶应用方法浅析
  9. 很多人不理解这个参数的 nl,nh:ESC * m nL nH d1... dk
  10. 游戏服务器的常用架构
  11. 面试了一个37 岁的程序员 有一些感悟
  12. ubuntu14关闭来宾账户
  13. 脱离低级趣味- Python ‘\r‘, ‘\n‘, ‘\r\n‘ 的彻底理解
  14. pics_IE的内容顾问,PICS评级和当今的ASP.NET Flakey
  15. bootstrapTable 根据条件隐藏某列
  16. SpringBoot + Springmvc集成guava
  17. 想成为管理者必须会讲的68个超级经典小故事
  18. java 奇数中文乱码_java web 乱码 整理
  19. MANACHER最长回文算法
  20. 【blast安装及使用】如何在Linux配置blast做序列对比

热门文章

  1. webpack中将打包后的文件复制到指定路径
  2. Chrome扩展框架-浏览器插件安装方法
  3. 安卓开发(一)环境搭建、基本程序与控件
  4. ajaxForm和ajaxSubmit
  5. 带你读懂Java GC日志信息 教你如何使用工具查看【图文演示】
  6. linux安装和简单使用minio client | mc命令
  7. t-io 入门篇(三)即时消息发送demo学习
  8. PointRend相关论文集
  9. DrugBank数据库以及其他介绍
  10. Java高并发秒杀API(四)之高并发优化