实现了HTTP文件的上传,现在我们看如何实现客户端的文件下载部分
主线程request
r = requests.head(url)
主进程卡在requests.head的请求中
函数起线程调用
reqHeadSize = ""
def Tre(requestUrl):
global reqHeadSize
reqHead = requests.head(requestUrl)
实例化类后起线程调用
class SubTre():
reqHeadSize = ""
def __init__(self):
self.reqHeadSize = "123"
def exec(self,requestUrl):
reqHead = requests.head(requestUrl)
self.reqHeadSize = int(reqHead.headers['content-length'])
起线程调用
tTre = SubTre()
t = threading.Thread(target=tTre.exec, kwargs={'requestUrl': url})
t.setDaemon(True)
t.start()
# t.join()
由于文件直接存储在项目\static\uploads\
目录下,可直接获取本地文件大小
def getFileSize(fileName):
# 获取项目根目录
cwd = sys.path[1]
# 拼接文件所在目录
filePath = cwd + "\\static\\uploads\\" + fileName
# 获取文件大小
fileSize = os.path.getsize(filePath)
return fileSize
json
join的原理就是依次检验线程池中的线程是否结束,没有结束就阻塞直到线程结束,如果结束则跳转执行下一个线程的join函数
- 阻塞主进程,专注于执行多线程中的程序
- 多线程多join的情况下,依次执行各线程的join方法,前头一个结束了才能执行后面一个
- 无参数,则等待到该线程结束,才开始执行下一个线程的join
- 参数timeout为线程的阻塞时间,如 timeout=2 就是罩着这个线程2s 以后,就不管他了,继续执行下面的代码
分块下载
import sys
import requests
import threading
import datetime
# 传入的命令行参数,要下载文件的url
url = sys.argv[1]
def Handler(start, end, url, filename):
headers = {'Range': 'bytes=%d-%d' % (start, end)}
r = requests.get(url, headers=headers, stream=True)
# 写入文件对应位置
with open(filename, "r+b") as fp:
fp.seek(start)
var = fp.tell()
fp.write(r.content)
def download_file(url, num_thread = 5):
r = requests.head(url)
try:
file_name = url.split('/')[-1]
file_size = int(r.headers['content-length']) # Content-Length获得文件主体的大小,当http服务器使用Connection:keep-alive时,不支持Content-Length
except:
print("检查URL,或不支持对线程下载")
return
# 创建一个和要下载文件一样大小的文件
fp = open(file_name, "wb")
fp.truncate(file_size)
fp.close()
# 启动多线程写文件
part = file_size // num_thread # 如果不能整除,最后一块应该多几个字节
for i in range(num_thread):
start = part * i
if i == num_thread - 1: # 最后一块
end = file_size
else:
end = start + part
t = threading.Thread(target=Handler, kwargs={'start': start, 'end': end, 'url': url, 'filename': file_name})
t.setDaemon(True)
t.start()
# 等待所有线程下载完成
main_thread = threading.current_thread()
for t in threading.enumerate():
if t is main_thread:
continue
t.join()
print('%s 下载完成' % file_name)
if __name__ == '__main__':
start = datetime.datetime.now().replace(microsecond=0)
download_file(url)
end = datetime.datetime.now().replace(microsecond=0)
print("用时: ", end='')
print(end-start)
分块下载
r = requests.get(url, stream=True)
f = open("F://Penguins.jpg", "wb")
for chunk in r.iter_content(chunk_size=512):
if chunk:
f.write(chunk)