断点传续 # 补充 mysql
1 断点续传 2 3 任务进行过程中,由于某些原因导致任务没有完成 4 在重新启动程序之后 可以接着上次断掉的位置继续传输 5 6 =========== ================ 服务器 7 =========== 50 8 ================ 9 10 11 1.客户端 需下载某个文件 12 输入一个文件名称 13 判断该文件是否已经下载 14 判断文件是否传输完毕 15 一个任务存在的状态 16 17 18 1.新任务 本地没有 19 文件不存在 并且任务记录中也不存在 20 2.任务未完成 本地有 但是不完整 21 文件已经存在 但是任务记录标记为未完成 22 3.任务已完成 本地有完整的数据 23 文件已经存在 任务标记为已完成 24 4.任务已经完成 但是数据被删除 25 文件不存在 任务标记为完成 26 27 任务记录? 28 新任务 需要添加到记录中 未完成 29 下载完成 修改记录为完成 30 需要哪些数据? 31 任务名称 32 文件名称 33 状态 34 未完成 35 已完成 36 {"name":False} 37 38 字典存储任务 需要永久存储 39 40 41 42 使用方法 43 将测试文件放在服务器的 serverFiles中
1 {"5.\u534f\u7a0b.mp4": true}
1 import json 2 import os 3 import socket 4 5 import struct 6 7 import logging 8 9 server = socket.socket() 10 11 server.bind(("127.0.0.1",1688)) 12 server.listen() 13 14 15 def recv_head(client): 16 head_len = client.recv(4) 17 if not head_len: 18 raise Exception("对方下线了!") 19 lens = struct.unpack("i",head_len)[0] 20 req = json.loads(client.recv(lens).decode("utf-8")) 21 return req 22 23 24 def send_rep(client,rep): 25 jdata = json.dumps(rep).encode("utf-8") 26 client.send(struct.pack("i",len(jdata))) 27 client.send(jdata) 28 29 while True: 30 client,addr = server.accept() 31 while True: 32 try: 33 req = recv_head(client) 34 # rep中必须包含 文件名称 35 filename = req["filename"] 36 37 38 path = os.path.join("serverFiles",filename) 39 if not os.path.exists(path): 40 rep = {"msg":"服务器不存在该文件!"} 41 send_rep(client,rep) 42 else: 43 # 发送文件信息 44 info = {"filename":filename,"filesize":os.path.getsize(path)} 45 send_rep(client,info) 46 47 # 发送文件数据 48 with open(path,"rb") as f: 49 f.seek(req["recv_size"],0) 50 while True: 51 data = f.read(2048) 52 if not data :break 53 client.send(data) 54 # 文件传输完毕 55 print("文件传输完毕!") 56 client.close() 57 break 58 except Exception as e: 59 logging.error(e) 60 client.close() 61 break
1 import os 2 3 import time 4 from mylib import * 5 import socket 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # 用于处理任务状态的工具类 22 class LogTool: 23 # 日志记录的文件名称 24 log_file = "file_log.txt" 25 # 初始化方法 26 def __init__(self): 27 #创建 记录文件 28 if not os.path.exists(self.log_file): 29 self.write_info({}) 30 31 # 用于获取文件状态的方法 32 def get_file_status(self,filename): 33 """ 34 :param filename: 35 :return: 1 表示完成 0 已存在但表示未完成 2 新任务 3 文件被删除 36 """ 37 # 先找任务记录看看 38 info = self.read_info() 39 if filename in info: #存在记录 40 if info[filename]: 41 # 记录显示为True 在判断文件是否已经存在 42 if os.path.exists(os.path.join("clientFiles",filename)): 43 return 1 44 else: 45 return 3 46 else: 47 return 0 48 else:# 不存在记录 49 return 2 50 51 def read_info(self): 52 with open(self.log_file,"rt") as f: 53 return json.load(f) 54 55 def write_info(self,info): 56 with open(self.log_file,"wt") as f: 57 json.dump(info,f) 58 59 # 添加新的新记录 60 def newtask(self,filename): 61 info = self.read_info() 62 info[filename] = False 63 self.write_info(info) 64 65 #标记为任务完成 66 def task_done(self, filename): 67 info = self.read_info() 68 info[filename] = True 69 self.write_info(info) 70 71 72 # =======================================TCP 部分 73 74 75 76 77 78 # 输入文件名称 79 filename = input("filename:").strip() 80 81 # 创建小工具 82 tool = LogTool() 83 84 # 获取任务的状态 85 st = tool.get_file_status(filename) 86 # " :return: 1 表示完成 0 已存在但表示未完成 2 新任务 3 文件被删除" 87 88 # 表示已经下载的大小 89 recv_size = 0 90 91 if st == 0: 92 # 要断点续传 要读取文件大小发给服务器 93 recv_size = os.path.getsize(os.path.join("clientFiles",filename)) 94 elif st == 1: 95 print("该任务已经完成!") 96 exit() 97 elif st == 2: 98 print("新任务") 99 else: 100 if input("文件被删除!是否重新下载?(y/n)") != "y": 101 exit() 102 103 # 信息中要包含已接受文件大小 104 info = {"filename":filename,"recv_size":recv_size} 105 106 107 client = socket.socket() 108 client.connect(("127.0.0.1",1688)) 109 110 # 发送报头信息 111 send_rep(client,info) 112 113 # 接收报头信息 114 rep = recv_head(client) 115 116 117 # 判断是文件信息还是错误信息 118 if "filename" in rep: 119 # 拼接文件路径 120 path = os.path.join("clientFiles", rep["filename"]) 121 122 123 buff_size = 2048 124 125 # 添加下载记录 126 tool.newtask(filename) 127 128 # 注意 必须使用ab模式 才能断点续传 129 with open(path,"ab") as f: 130 while recv_size < rep["filesize"]: 131 if buff_size < rep["filesize"] - recv_size: 132 data = client.recv(buff_size) 133 else: 134 data = client.recv(rep["filesize"] - recv_size) 135 f.write(data) 136 recv_size += len(data) 137 # print(recv_size/rep["filesize"]) 138 139 # 标记完成 140 tool.task_done(filename) 141 142 else: 143 print("error") 144 print(rep) 145 146 147 148 149 150 151 152 # 发送文件报头
1 import json 2 import struct 3 def recv_head(client): 4 head_len = client.recv(4) 5 if not head_len: 6 raise Exception("对方下线了!") 7 lens = struct.unpack("i", head_len)[0] 8 req = json.loads(client.recv(lens).decode("utf-8")) 9 return req 10 11 12 def send_rep(client,rep): 13 jdata = json.dumps(rep).encode("utf-8") 14 client.send(struct.pack("i",len(jdata))) 15 client.send(jdata)