Python 多线程下载大文件
*仅实现,可优化
*因为第三方下载请求次数限制,个人设备网络限制,多线程实现后效果一般。
已知:
1、网络环境较差时,下载线程没有全部下载完成就走了后面的逻辑;(bug)
2、实现线程进度条、线程断点续传;(优化)
3、下载文件处理;(优化)
拆分url,total_size作为self.变量
def get_url(self):
'''
获取下载url
'''
down_token = self.download_token()
releaseid = self.findApk()
print("%s : %s(%s) %s" % (self.which, self.version, self.build, self.changelog))
url = "http://download.bq04.com/apps/"+self.id+"/install?download_token="+down_token+"&release_id="+releaseid
return url
def get_total_size(self):
'''
获取下载文件大小
'''
Response = requests.get(self.url, stream=True, verify=False)
# 总大小
total_size = int(Response.headers.get('content-length', 0))
return total_size
获取每个线程下载大小。逻辑:按照线程数拆分计算每个线程下载的字节,有余数的情况下,最后几个字节放进最后一个线程
def get_thread_download(self):
'''
获取每个线程下载大小
'''
thread_size = {}
cut_size = self.total_size // self.thread_num
start_bytes = -1
for i in range(1, self.thread_num + 1):
thread_size[i] = [start_bytes + 1, cut_size * i]
start_bytes = cut_size * i
if start_bytes != self.total_size:
thread_size[self.thread_num][1] = self.total_size
return thread_size
def create_thread(self):
"""
开启多线程下载
"""
start = time()
self.url = self.get_url()
self.total_size = self.get_total_size()
thread_size = self.get_thread_download()
t = {}
for i in range(1, self.thread_num + 1):
t[i] = Thread(target=self.loadAPKs, args=(thread_size[i][0], thread_size[i][1], i))
t[i].start()
for i in range(1, self.thread_num + 1):
t[i].join()
end = time()
print('总共耗费了%.2f秒.' % (end - start))
多线程下载函数。逻辑:根据线程的传参下载对应字节
def loadAPKs(self, start_bytes, end_bytes, tread_count):
'''
多线程下载ing
'''
paths = str(downloadPath) + "/" + str(tread_count) + ".tmp"
header = {"Range": f"bytes={start_bytes}-{end_bytes}"}
Req = requests.get(self.url, headers=header, stream=True, verify=False)
file = open(paths, "wb")
for chunk in Req.iter_content(chunk_size=512):
if chunk:
file.write(chunk)
下载完成后,以字节合并所有文件
def combine_file(self):
'''
合并文件
'''
self.create_thread()
paths = str(downloadPath) + "/Hello_" + self.version + "_" + self.build + "_" + self.which + ".apk"
print(paths)
with open(paths, "ab") as f:
for i in range(1, self.thread_num + 1): # 根据id查找文件
print(i)
with open(str(downloadPath) + "/" + str(i) + ".tmp", "rb") as bytes_f:
f.write(bytes_f.read())
return paths
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix