断点续传 进度条 文件上传
import socketserver import json import os import shutil CODE = {'1001':'不存在文件,从头开始上传','1002':'断点续传'} def upload(flie_info,conn,username): """ 服务端断点续传 :param flie_info: :param conn: :param username: :return: """ # 获取文件信息 md5_val = flie_info.get('md5_val')#获取加密文件的md5字符串 file_name = flie_info.get('file_name')# 获取文件名 file_size = flie_info.get('file_info')# 获取文件大小 file_name_path = os.path.join('home',username,file_name)#文件路径拼接 file_md5_path = os.path.join('home',username,md5_val) # 判断文件是否存在 if not os.path.exists(file_md5_path):#不存在文件.开始上传完整文件 response = {'code':1001} conn.sendall(json.dumps(response).encode('utf-8')) # 不存在MD5加密文件要发送状态码给客户端让他准备(类似于三次握手) # 接收完整文件内容并且写到本地 with open(file_md5_path,'wb') as f: recv_data = 0 while recv_data < file_size: data = conn.recv(1024) f.write(data) recv_data += len(data) # 修改文件名 shutil.move(file_md5_path,file_name_path) else:# 存在文件名但是不完整的情况下 exise_size = os.path.getsize(file_md5_path) # 拿到已经存在的文件大小,打包发送给客户端处理 response = {'code':1002,"size":exise_size} conn.sendall(json.dumps(response).encode('utf-8')) # 接收到客户端发送的剩余文件内容 with open(file_md5_path,'ab') as f: while exise_size < file_size: data = conn.recv(1024) f.write(data) f.flush() exise_size += len(data) # 修改文件名 shutil.move(file_md5_path,file_name_path) class MyServer(socketserver.BaseRequestHandler): def handle(self): print('server is waiting.....') # 接收命令 file_json_bytes = self.request.recv(8096) file_info = json.loads(file_json_bytes.decode('utf-8')) if file_info.get('cmd')=='upload': upload(file_info,self.request,'yuanwei') if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('127.0.0.1',8003),MyServer) server.serve_forever()
import socket import os import json import hashlib def path_md5(file_path): m = hashlib.md5() for line in file_path: m.update(line) return m.hexdigest() def jdt(size,total_size): """ 显示进度条 :param size: :param total_size: :return: """ val = int(size/total_size*100) print("\r%s%%|%s"%(val,'*'*val),end='') def send_file(exits_size,total_size): """ 发送文件 :param exits_size: 开始读取字节的位置 :param total_size: 文件总字节的大小 :return: """ with open(file_path,'rb')as f: f.seek(exits_size) while exits_size < total_size: data = f.read(1024) client.sendall(data) exits_size += len(data) jdt(exits_size,total_size) print('上传成功') def upload(file_path): """ 文件上传(含断点) :param file_path: :return: """ md5_val = path_md5(file_path)# 获取加密的文件字符串格式 file_name = os.path.basename(file_path)#获取文件名 file_size = os.path.getsize(file_path) file_info = {'cmd':'upload', 'md5_val':md5_val, "file_name":file_name, 'file_size':file_size } file_json_bytes = json.dumps(file_info).encode('utf-8') client.sendall(file_json_bytes) response = client.recv(8096).decode('utf-8') if response['code'] == 1001:#完整上传 send_file(0,file_size) else: exit_size = response['size'] send_file(exit_size,file_size) client = socket.socket() client.connect(('127.0.0.1',8003)) while 1: user_inp = input('请输入要执行的命令>>(upload|路径)') cmd, file_path = user_inp.strip().split("|") if cmd == 'upload': upload(file_path)