网络编程学习(10)/ FTP项目(4) ——文件下载和下载断点续存功能

  • 服务端
    • `lib 文件夹下 main.py`
  • 客户端
    • `client文件夹下 FTPClient.py 代码 interactive函数 增加部分`
    • `client文件夹下 FTPClient.py `
  • 运行结果
    • 终端命令结果
    • 运行后项目目录

服务端

lib 文件夹下 main.py

    def _get(self, header_dir):"""从服务端下载文件"""filename = header_dir.get("filename")# 判断当前路径是否存在该文件# 存在,上传文件# 不存在,返回状态码full_path = os.path.join(self.current_dir, filename)if os.path.isfile(full_path):# 文件存在total_size = os.path.getsize(full_path)self.send_response(status_code=400, total_size=total_size, current_dir = self.current_dir)# 发送文件with open(full_path, "rb") as f:for line in f:self.conn.send(line)else:self.send_response(status_code=401)def _re_get(self,header_dic):"""下载断点续存"""filename = header_dic.get("filename")current_dir = header_dic.get("current_dir")total_size = header_dic.get("total_size")recv_size = header_dic.get("recv_size")full_path = os.path.join(current_dir, filename)print(full_path)if os.path.isfile(full_path): # 如果文件存在if os.path.getsize(full_path) == total_size: # 如果文件大小一致,就认为是同一个文件self.send_response(status_code=402)with open(full_path, "rb") as f:f.seek(recv_size) # 从下载中断的地方开始发送for line in f:self.conn.send(line)else:self.send_response(status_code=401) # 文件不存在else:self.send_response(status_code=401) # 文件不存在

客户端

client文件夹下 FTPClient.py 代码 interactive函数 增加部分

    def interactive(self):"""交互指令"""if self.auth(): # 登陆成功self.unfinished_download_check() # 检查未下载完成的文件......

client文件夹下 FTPClient.py

    def unfinished_download_check(self):"""下载断点续存功能"""if list(self.shelve_obj_download.keys()): # 如果有未下载完成的文件print("-------Unfinished download list------")for index, filename in enumerate(self.shelve_obj_download.keys()):print("%s      %s      %s" % (index, filename, self.shelve_obj_download[filename][1])) # 第几个文件,文件名,文件总大小while True:choice = input("[select file index to re-get]>>: ").strip()if not choice: continue # 如果为空if choice == "back": break # 退出if choice.isdigit(): # 判断是否是数字choice = int(choice) # 转化为整型if choice <= index: # 选择在范围内filename = list(self.shelve_obj_download.keys())[choice]current_dir = self.shelve_obj_download[filename][0]total_size = self.shelve_obj_download[filename][1]recv_size = os.path.getsize("%s.download" % filename) # 中断前下载的文件大小self.create_header_send(action_type="re_get", filename=filename, current_dir=current_dir, total_size=total_size, recv_size=recv_size)response = self.get_response()if response.get("status_code") == 402:# 进度条progress_bar = self.progress_bar(total_size=total_size, res_size=recv_size, last_size=recv_size)progress_bar.__next__()# 循环接收文件with open("%s.download" % filename, "ab") as f: # ”ab"表示追加写入while recv_size < total_size:data = self.client.recv(self.MSG_SIZE)recv_size += len(data)progress_bar.send(recv_size)f.write(data)else:print("\n")print("file %s has re-downloaded !" % filename)if os.path.isfile(filename):  # 如果同命名的文件存在,就加上时间戳作为后缀os.rename("%s.download" % filename, "%s.%s" % (filename, str(time.time())))else:os.rename("%s.download" % filename, filename)del self.shelve_obj_download[filename] # 删除,因为文件已下载完成else:print(response.get("status_msg"))del self.shelve_obj_download[filename] # 删除,因为文件不存在else:print("choice does exist !")else:print("please supply number !")def progress_bar(self, total_size, res_size=0, last_size=0):"""进度条功能"""while True:res_size = yield total_sizepercent = int(res_size / total_size * 100)if res_size > last_size:print("#" * int(percent / 2) + "{percent}%".format(percent=percent), end="\r", flush=True) # "\\r" 表示打印时覆盖已打印的内容last_size = res_sizedef get(self, command):"""从服务端下载文件"""# 当前功能只实现一次一个文件下载,所以至少要传入一个参数,多余参数不予考虑if self.parameter_length_judgment(command, most_size=1):filename = command[0]self.create_header_send(action_type="get", filename=filename)response = self.get_response()if response.get("status_code") == 400:total_size = response.get("total_size")self.current_dir = response.get("current_dir")# print(self.current_dir)# 进度条progress_bar = self.progress_bar(total_size=total_size)progress_bar.__next__()# 记录未下载完成的文件,为断点续存做准备self.shelve_obj_download[filename] = (self.current_dir, total_size) # 记录文件在服务端的路径以及文件的总大小# 循环接收文件res_size = 0with open("%s.download" % filename,"wb") as f:while res_size < total_size:data = self.client.recv(self.MSG_SIZE)res_size += len(data)progress_bar.send(res_size)f.write(data)else:print("\n")print("file %s has downloaded !" % filename)if os.path.isfile(filename): # 如果同命名的文件存在,就加上时间戳作为后缀os.rename("%s.download" % filename, "%s.%s" % (filename, str(time.time())))else:os.rename("%s.download" % filename, filename)del self.shelve_obj_download[filename] # 下载完成后删除else:print(response.get("status_msg"))

运行结果

终端命令结果

运行后项目目录

网络编程学习(10)/ FTP项目(4) ——文件下载和下载断点续存功能相关推荐

  1. 网络编程学习(11)/ FTP项目(5) ——文件上传和上传断点续存功能

    网络编程学习(11)/ FTP项目(5) --文件上传和上传断点续存功能 `服务端 lib 文件夹下的 main.py 状态码的变化` 文件上传功能 `服务端 lib 文件夹下的 main.py` ` ...

  2. 网络编程学习(9)/ FTP项目(3) ——目录切换、目录查看功能

    网络编程学习(9)/ FTP项目(3) --目录切换.目录查看功能 调用功能函数以及对参数数量进行判断 客户端 `server 文件夹下 FTPClient.py` 状态码的变化 服务端 `lib 文 ...

  3. 谈一谈网络编程学习经验(06-08更新)

    谈一谈网络编程学习经验 陈硕 giantchen@gmail.com blog.csdn.net/Solstice 2011-06-08 PDF 版下载:https://github.com/down ...

  4. 15Java网络编程学习笔记

    Java网络编程学习笔记 文章目录 1 网络基础 1.1 网络通信 1.2 网络 1.3 IP地址 1.5 域名 1.6 端口号 1.7 网络通信协议 1.8 TCP协议 1.9 UDP协议 2 In ...

  5. python网络编程学习笔记(二)

    python网络编程学习(四) 多用途客户端协议 一.ftp 功能:上传下载文件,删除命名文件,建立删除目录,自动压缩,保存目录 1.代码: #coding=utf-8 '''连接远程ftp服务器,显 ...

  6. C++网络编程学习:服务端多线程分离业务处理高负载

    网络编程学习记录 使用的语言为C/C++ 源码支持的平台为:Windows / Linux 笔记一:建立基础TCP服务端/客户端  点我跳转 笔记二:网络数据报文的收发  点我跳转 笔记三:升级为se ...

  7. 华清远见网络编程学习总结

    这周进行了两天半的网络编程学习和两天来做自己的项目. 首先是学习了UDP(UDP:不保证可靠的无连接协议,在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输)的服务端和客户端.其适用的情况 ...

  8. C++ 网络编程学习指南

    C,C++网络编程学习简明指南 1. 扎实的C,C++基础知识 参考资料<C程序设计>,<C++ primer>. 2. TCP/IP协议 经典书是:W.Richard Ste ...

  9. C++网络编程学习:网络数据报文的收发

    网络编程学习记录 使用的语言为C/C++ 源码支持的平台为:Windows 笔记一:建立基础TCP服务端/客户端  点我跳转 笔记二:网络数据报文的收发  点我跳转 笔记三:升级为select网络模型 ...

最新文章

  1. 关于数据表中插入数据报错(pymysql.err.IntegrityError) (1062, “Duplicate entry ‘0112‘ for key ‘‘teacher.PRIMARY‘“)
  2. eclipse下编译hadoop源代码(转)
  3. 软考高项之各大管理计划内容-攻坚记忆
  4. wsl 或者window terminal 下出现Java 14 switch expressions unrecognized解决方法:升级java jdk到14 or later
  5. 配置防盗链、 访问控制Directory 、访问控制FilesMatch
  6. 使用聚合的方式实现静态代理
  7. Bash脚本:怎样一行行地读文件(最好和最坏的方法)
  8. phpcmsV9 如何开启“会员注册” - 教程篇
  9. 阿里巴巴,华为都不在58上招聘么?
  10. dao-service-servlet-jsp构建简易web通讯录(三层开发)知识点1
  11. Zookeeper实现简单的分布式RPC框架
  12. 最新全国移动联通基站数据升级包(2013年4月)
  13. 比特币 POW 白皮书 区块篡改成功的概率 代码 注释详解
  14. 磁盘不见了只剩一个c盘_非常的奇葩,终于解决了硬盘从盘盘符消失的问题
  15. 简述RUP软件过程模型的特点
  16. CPI通常用于衡量计算机性能,2021考研408计算机组成原理习题:计算机的性能指标...
  17. My Forty-eighth Page - 组合 - By Nicolas
  18. Linux基础指令入门 2
  19. 【直击DTCC】浪潮霍俊路详解数据库集群锁机制管理
  20. vue子组件修改props传进来的值、回调函数

热门文章

  1. Resilience4j简介
  2. 5. SAP S/4 运维基础知识(Basic Knowledge) - SAP S/4 Basis Learning
  3. 团队管理那点破事!OKR绩效、核心人才、面试、技术分享、研发流程....
  4. 查看新增串口、USB设备
  5. 请教各位仁兄 ,如何给delphi7增加gdi+的功能?
  6. Android手机哪个悬浮好用,别羡慕苹果了,安卓悬浮神器比 iPhone 好用太多!
  7. ora**cle数据库过期问题
  8. 二黑告别了鹅厂,回去老家当富豪!
  9. 面对众多云数据库,应该使用哪个云数据库好?
  10. 又一重磅利好,海南撒10亿基金发展区块链技术