【python】HTTP 文件下载

实现了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函数

  1. 阻塞主进程,专注于执行多线程中的程序
  2. 多线程多join的情况下,依次执行各线程的join方法,前头一个结束了才能执行后面一个
  3. 无参数,则等待到该线程结束,才开始执行下一个线程的join
  4. 参数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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sysu_lluozh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值