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)