1.默认情况下,requests 会一次性下载整个响应内容。对于++大文件或流式数据++,如果希望边下载边处理数据,而不是等待整个文件下载完成。可以通过++设置 stream 参数为 True++来实现这一点。

import requests

response = requests.get('http://example.org/large-file', stream=True)

with open('large-file', 'wb') as fd:
    for chunk in response.iter_content(chunk_size=1024):  # 每次读取 1024 字节
        fd.write(chunk)

在这个例子中,++response.iter_content()方法用于分块读取响应内容++,chunk_size 参数定义了每个块的大小。


2.如何获取文件总大小?用请求体的Content-Length字段,其单位是字节

res = requests.get(download_url, stream=True)
file_size = int(res.headers.get('Content-Length')) 

3.进度条的实现如下:这里的进度条总长为10个黑块,每次拼接进度百分比乘以10这么多的黑块。这里直接使用Python中字符串乘法来拼接指定数量的字符串。

with open('./large-file', 'wb') as fd:
    size = 0
    progressBar = ''
    for chunk in res.iter_content(chunk_size=1024):  # 每次读取 1024 字节
        fd.write(chunk)
        size += len(chunk)
        progress = size/file_size
        progressBar = int(progress*10) * '████'

4.最后一个问题:如果我们用print函数输出进度条,那就会每一次迭代都会输出一行进度条,最后在屏幕上输出很多行。但是我们平时看到的进度条都是屏幕上只有一行,然后不断更新。这个怎么实现呢?我们可以用\r(回车符)来返回行首,这样下一次输出时就会覆盖旧的进度条。而且我们可以使用sys.stdout.flush()来强制刷新输出缓冲区。代码如下:

with open('./large-file', 'wb') as fd:
    size = 0
    progressBar = ''
    for chunk in res.iter_content(chunk_size=102400):  # 每次读取 1024 字节
        fd.write(chunk)
        size += len(chunk)
        progress = size/file_size
        progressBar = int(progress*10) * '████'
        sys.stdout.write(f"\r {progress*100:.2f}% {progressBar}")
        sys.stdout.flush()  # 强制刷新输出缓冲区

把它封装成一个函数,完整代码如下: image.png