断点续传

server

import socketserver
import struct
import hashlib
import os
import json

class Mysocket(socketserver.BaseRequestHandler):
“”""
接收 字典 文件 信息 长度 字典 文件 信息
判断是否存在未传完的该文件
发送truck类型的数据告知客户端光标位置
最后接收文件
文件传输完毕后发送ok到客户端
salt = ‘salt’
等待客户端发送md5值
验证通过后发送上传结果到客户端
“”"
len_file = 0 # 已经接收文件的长度
md5 = hashlib.md5(b’salt’)
int_head = 0 # file_info 大小
file_info = {} # 文件信息 字典类型 {‘file_name’:’’, ‘file_size’:’’}
file_name = ‘’ # 文件名
file_path = ‘’ # 文件要写入的路径
file_size = 0 # 要接收的文件大小
send_seek = 0 # 发送服务器已经存在光标位置
md5_file_path = ‘’

def file_recv_file(self):  # 没有上传过文件 开始上传文件
    with open(self.file_path, mode='wb') as f:
        while self.len_file < self.file_size:  # 数据传输总长度小于 文件大小
            file_data = self.request.recv(1024)  # 每次接收的数据
            f.write(file_data)
            self.len_file += len(file_data)  # 目前文件总长度

def file_recv_file_have(self):  # 接收文件 计算文件md5 写入md5文件
    with open(self.file_path, mode='rb+') as f:  # 移动光标到send_seek 写入每次收到1024个字节
        f.seek(self.send_seek)
        while self.len_file < self.file_size:  # 数据传输总长度小于 文件大小
            file_data = self.request.recv(1024)  # 每次接收的数据
            f.write(file_data)
            self.len_file += len(file_data)  # 目前文件总长度

def file_recv_info(self):  # 接收 文件信息 给self.file_info赋值
    file_info_data = self.request.recv(self.int_head)
    self.file_info = json.loads(file_info_data.decode('utf-8'))

def handle(self):
    try:
        data_head = self.request.recv(4)  # 接收 file_info 大小
        print(data_head)
        self.int_head = struct.unpack('i', data_head)[0]  # 头 file_info 长度
        self.file_recv_info()  # 接收 文件信息 给self.file_info赋值
        self.file_name = self.file_info["file_name"]
        self.file_size = int(self.file_info["file_size"])  # 给server对象定义文件大小
        self.file_path = os.path.join('e:/', self.file_name)  # 文件要写入的路径
        self.md5_file_path = os.path.join(os.path.dirname(self.file_path),
                                          self.file_name.split('.')[0] + '_md5')  # md5文件路径
        with open(self.md5_file_path, mode='w', encoding='utf-8') as f:
            pass
        if not os.path.isfile(self.file_path):  # 判断 是否存在文件 如果不存在正常写入
            self.request.send(struct.pack('i', 0))  # 发送告知客户端已存在文件长度为0
            self.file_recv_file()  # 开始接收文件
        elif os.path.isfile(self.file_path):  # 如果 文件传过一半
            with open(self.file_path, mode='rb') as f:
                f.seek(0,2)
                self.send_seek = f.tell()
            self.len_file = os.path.getsize(self.file_path)  # 判断 e盘下之前传过的文件大小存入self.len_file中
            self.request.send(struct.pack('i', self.send_seek))  # 发送告知客户端已存在文件光标位置为self.send_seek
            self.file_recv_file_have()  # 开始接收文件
        self.request.send('OK'.encode('utf-8'))  # 文件传输完毕后发送通知
        data_md5 = self.request.recv(1024).decode('utf-8')
        with open(self.file_path, 'rb') as f:
            for line in f:
                self.md5.update(line)
            res = self.md5.hexdigest()
        if data_md5 == res:
            self.request.send('文件上传成功'.encode('utf-8'))
        else:
            self.request.send('文件上传失败请重新上传'.encode('utf-8'))
    except ConnectionResetError as e:
        pass

server = socketserver.ThreadingTCPServer((‘192.168.3.7’, 9000), Mysocket)
server.serve_forever()

client

“”""
发送 字典 文件 信息 长度 字典 文件 信息 到服务端
判断是否存在未传完的该文件
发送truck类型的数据告知客户端光标位置
最后接收文件
文件传输完毕后发送ok到客户端
salt = ‘salt’
等待客户端发送md5值
验证通过后发送上传结果到客户端
“”"

import socket
import os
import json
import struct
import hashlib

class Myclient(object):
file_name = ‘’ # 要上传的文件名
file_size = 0 # 要上传的文件大小
head_len = struct.pack(‘i’, 0) # file_info的信息长度 struct格式
json_info_bytes = b’’ # 信息 json 字节

def __init__(self, path):
    self.file_path = path # 要上传的文件路径

def file_info(self):  # 赋值file_info_bytes
    self.file_name = os.path.split(self.file_path)[1]
    self.file_size = os.path.getsize(self.file_path)
    self.json_info_bytes = json.dumps({"file_name": self.file_name, "file_size": self.file_size}).encode('utf-8')

def head_pack(self):  # 赋值4位file_info 的字节长度
    self.head_len = struct.pack('i', len(self.json_info_bytes))

def run(self):
    self.file_info()
    self.head_pack()
    return self.head_len + self.json_info_bytes

md5 = hashlib.md5(b’salt’)
while 1:
client = socket.socket()
client.connect((‘192.168.3.7’, 9000))
path = input(‘请输入要上传的文件’)
obj = Myclient(path)
obj.run()
client.send(obj.run())
data_seek = client.recv(4)
print(data_seek)
seek = struct.unpack(‘i’, data_seek)[0]
with open(obj.file_path, mode=‘rb’) as f:
f.seek(seek)
for line in f:
client.send(line)
data_ok = client.recv(1024).decode(‘utf-8’)
if data_ok == ‘OK’:

    with open(obj.file_path, mode='rb') as f1:
        for line in f1:
            md5.update(line)
    client.send(md5.hexdigest().encode('utf-8'))

print(client.recv(1024).decode('utf-8'))

经过测试成功,但不够严谨大神们可以指点指点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值