大文件下载以及进度条展示和MD5校验
时间:2022-06-05
本文章向大家介绍大文件下载以及进度条展示和MD5校验,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
使用socket网络,上传一个视频,大小在3G左右
能够显示进度条,显示花费时间
下载使用TCP协议
server向client发送文件
新建文件server.py,代码如下:
import os
import json
import socket
import struct
filepath = r'E:BaiduYunDownload[电影天堂www.dy2018.com]移动迷宫3:死亡解药BD国英双语中英双字.mp4'
sk = socket.socket()
sk.bind(('127.0.0.1', 9000))
sk.listen()
conn, addr = sk.accept()
filename = os.path.basename(filepath)
filesize = os.path.getsize(filepath)
dic = {'filename': filename, 'filesize': filesize}
str_dic = json.dumps(dic).encode('utf-8')
len_dic = len(str_dic)
length = struct.pack('i', len_dic)
conn.send(length) # dic的长度
conn.send(str_dic) # dic
with open(filepath, 'rb') as f: # 文件
while filesize:
content = f.read(4096)
conn.send(content)
filesize -= len(content)
'''
这里不能减等4096,因为文件,最后可能只有3字节。
要根据读取的长度len(content),来计算才是合理的。
'''
conn.close()
新建文件client.py,代码如下:
import json
import struct
import socket
import sys
import time
def processBar(num, total): # 进度条
rate = num / total
rate_num = int(rate * 100)
if rate_num == 100:
r = 'r%s>%d%%n' % ('=' * rate_num, rate_num,)
else:
r = 'r%s>%d%%' % ('=' * rate_num, rate_num,)
sys.stdout.write(r)
sys.stdout.flush
start_time = time.time() # 开始时间
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
dic_len = sk.recv(4)
dic_len = struct.unpack('i',dic_len)[0]
dic = sk.recv(dic_len)
str_dic = dic.decode('utf-8')
dic = json.loads(str_dic)
with open(dic['filename'],'wb') as f: # 使用wb更严谨一些,虽然可以使用ab
content_size = 0
while True:
content = sk.recv(4096)
f.write(content) # 写入文件
content_size += len(content) # 接收大小
processBar(content_size,dic['filesize']) # 执行进度条函数
if content_size == dic['filesize']:break # 当接收的总大小等于文件大小时,终止循环
sk.close() # 关闭连接
end_time = time.time() # 结束时间
print('本次下载花费了{}秒'.format(end_time - start_time))
先执行server.py,再执行client.py,效果如下:
上面效果展示了100个等号,太长了,那么要缩减到1/3呢?
修改进度条函数
def processBar(num, total): # 进度条
rate = num / total
rate_num = int(rate * 100)
if rate_num == 100:
r = 'r%s>%d%%n' % ('=' * int(rate_num / 3), rate_num,) # 控制等号输出数量,除以3,表示显示1/3
else:
r = 'r%s>%d%%' % ('=' * int(rate_num / 3), rate_num,)
sys.stdout.write(r)
sys.stdout.flush
再次执行,效果如下:
再来一个高级版,显示绿色的飞机
代码如下:
def processBar(num, total): # 进度条
rate = num / total
rate_num = int(rate * 100)
pretty = '✈'
if rate_num == 100:
r = 'r 33[32m{} 33[0m{}%n'.format(pretty * int(rate_num / 5), rate_num,)
else:
r = 'r 33[32m{} 33[0m{}%'.format(pretty * int(rate_num / 5), rate_num,)
sys.stdout.write(r)
sys.stdout.flush
再次执行,效果如下:
再来一个每秒换色
导入一个随机换色类
import random
class Prompt(object): # 提示信息显示
colour_dic = {
'red': 31,
'green': 32,
'yellow': 33,
'blue': 34,
'purple_red': 35,
'bluish_blue': 36,
'white': 37,
}
def __init__(self):
pass
@staticmethod
def display(msg, colour='white'):
choice = Prompt.colour_dic.get(colour)
# print(choice)
if choice:
info = " 33[1;{};1m{} 33[1;0m".format(choice, msg)
return info
else:
return False
def random_color(msg): # 随机换色
colour_list = []
for i in Prompt.colour_dic:
colour_list.append(i)
length = len(colour_list) - 1 # 最大索引值
index = random.randint(0, length) # 随机数
ret = Prompt.display(msg, colour_list[index]) # 随机颜色
return ret
修改client.py
from Prompt import Prompt
def processBar(num, total): # 进度条
rate = num / total
rate_num = int(rate * 100)
pretty = Prompt.random_color('✈') # 随机换色
if rate_num == 100:
r = 'r{}{}%n'.format(pretty * int(rate_num / 5), rate_num,)
else:
r = 'r{}{}%'.format(pretty * int(rate_num / 5), rate_num,)
sys.stdout.write(r)
sys.stdout.flush
再次执行,效果如下:
增加MD5校验
server.py
import os
import json
import socket
import struct
import hashlib
sk = socket.socket()
sk.bind(('127.0.0.1', 9000))
sk.listen()
conn, addr = sk.accept()
filename = '[电影天堂www.dy2018.com]移动迷宫3:死亡解药BD国英双语中英双字.mp4' # 文件名
absolute_path = os.path.join('E:BaiduYunDownload',filename) # 文件绝对路径
buffer_size = 1024*1024 # 缓冲大小,这里表示1MB
md5obj = hashlib.md5()
with open(absolute_path, 'rb') as f:
while True:
content = f.read(buffer_size) # 每次读取指定字节
if content:
md5obj.update(content)
else:
break # 当内容为空时,终止循环
md5 = md5obj.hexdigest()
print(md5) # 打印md5值
dic = {'filename':filename,
'filename_md5':str(md5),'buffer_size':buffer_size,
'filesize':os.path.getsize(absolute_path)}
str_dic = json.dumps(dic).encode('utf-8')
len_dic = len(str_dic)
length = struct.pack('i', len_dic)
conn.send(length) # dic的长度
conn.send(str_dic) # dic
with open(absolute_path, 'rb') as f: # 文件
while dic['filesize']:
content = f.read(dic['buffer_size'])
conn.send(content)
dic['filesize'] -= len(content)
'''
这里不能减等4096,因为文件,最后可能只有3字节。
要根据读取的长度len(content),来计算才是合理的。
'''
conn.close()
client.py
import json
import struct
import socket
import sys
import time
import hashlib
import os
from Prompt import Prompt
def processBar(num, total): # 进度条
rate = num / total
rate_num = int(rate * 100)
pretty = Prompt.random_color('✈')
if rate_num == 100:
r = 'r{}{}%n'.format(pretty * int(rate_num / 5), rate_num,)
else:
r = 'r{}{}%'.format(pretty * int(rate_num / 5), rate_num,)
sys.stdout.write(r)
sys.stdout.flush
start_time = time.time() # 开始时间
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
dic_len = sk.recv(4)
dic_len = struct.unpack('i',dic_len)[0]
dic = sk.recv(dic_len)
str_dic = dic.decode('utf-8')
dic = json.loads(str_dic)
md5 = hashlib.md5()
with open(dic['filename'],'wb') as f: # 使用wb更严谨一些,虽然可以使用ab
content_size = 0
while True:
content = sk.recv(dic['buffer_size']) # 接收指定大小
f.write(content) # 写入文件
content_size += len(content) # 接收大小
md5.update(content) # 摘要
processBar(content_size,dic['filesize']) # 执行进度条函数
if content_size == dic['filesize']:break # 当接收的总大小等于文件大小时,终止循环
md5 = md5.hexdigest()
print(md5) # 打印md5值
if dic['filename_md5'] == str(md5):
print(Prompt.display('md5校验正确--下载成功','green'))
else:
print(Prompt.display('文件验证失败', 'red'))
os.remove(dic['filename']) # 删除文件
sk.close() # 关闭连接
end_time = time.time() # 结束时间
print('本次下载花费了{}秒'.format(end_time - start_time))
执行输出:
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 微信小程序 buton清除默认样式
- 正则replace 回调函数里接收的参数是什么?
- 微信小程序使用pako.js的踩坑笔记
- Koa - 初体验(写个接口)
- Koa - 中间件(理解中间件、实现一个验证token中间件)
- Koa - 使用koa-multer上传文件(上传限制、错误处理)
- 原生js 复制内容到剪切板
- Vue - watch高阶用法
- 小程序如何支持使用 async/await (构建npm版)
- require.context批量引入文件
- Node笔记 - process.cwd() 和 __dirname 的区别
- 小程序如何支持使用 async/await
- 小程序 - 如何自定义导航栏
- protobuf 语法 与 protocol-buffers 的使用
- 小程序 - 简单实现mixin功能