python支持断点续传的多线程下载示例


当然,Python 支持断点续传的多线程下载可以通过多种方式实现,但通常会用到 `threading` 库来处理多线程,以及 `requests` 库来发送 HTTP 请求。这里,我将给出一个简化的示例,说明如何实现这一功能。注意,这个示例主要关注多线程和断点续传的逻辑,而不是完整的生产级代码。

首先,确保你已经安装了 `requests` 库。如果没有安装,可以通过 pip 安装:


pip install requests

接下来是 Python 代码示例:


import requests
import threading
from requests.exceptions import HTTPError

class ThreadDownload:
    def __init__(self, url, start_byte, end_byte, file_path, lock):
        self.url = url
        self.start_byte = start_byte
        self.end_byte = end_byte
        self.file_path = file_path
        self.lock = lock
        self.headers = {'Range': f'bytes={self.start_byte}-{self.end_byte}'}

    def download_chunk(self):
        try:
            response = requests.get(self.url, headers=self.headers, stream=True)
            response.raise_for_status()

            with open(self.file_path, 'r+b') as file:
                file.seek(self.start_byte)
                for chunk in response.iter_content(chunk_size=8192):
                    if chunk:
                        file.write(chunk)
                        # 可以在这里添加进度条更新等逻辑

        except HTTPError as http_err:
            print(f'HTTP error occurred: {http_err}')
        except Exception as err:
            print(f'An error occurred: {err}')

def main(url, file_name, num_threads=4):
    file_path = file_name
    total_size = int(requests.head(url).headers['Content-Length'])
    chunk_size = total_size // num_threads

    threads = []
    lock = threading.Lock()

    for i in range(num_threads):
        start_byte = i * chunk_size
        if i == num_threads - 1:
            end_byte = total_size - 1
        else:
            end_byte = start_byte + chunk_size - 1

        thread = threading.Thread(target=ThreadDownload(url, start_byte, end_byte, file_path, lock).download_chunk)
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

    print(f"Download of {file_name} completed.")

# 使用示例
if __name__ == "__main__":
    url = 'http://example.com/largefile.zip'  # 示例 URL,请替换为实际文件的 URL
    file_name = 'downloaded_file.zip'  # 保存到本地的文件名
    main(url, file_name, 4)  # 假设我们使用 4 个线程来下载

**注意**:

1. 这个示例假设服务器支持 HTTP Range 请求,并且文件的大小在请求头 `Content-Length` 中可用。

2. 示例中没有实现真正的断点续传逻辑,即在下载过程中如果程序崩溃,它不会从上次停止的地方继续下载。要实现这一功能,你需要记录每个线程下载的最后一个字节的位置,并在程序重启时检查这些位置。

3. 真实应用中,你可能还需要处理网络错误、超时等问题,以及实现更复杂的进度条更新和日志记录。

4. 示例中的 `lock` 实际上在这个简单的写入场景中并没有使用,但在多线程中操作共享资源(如更新UI或日志)时,锁是非常重要的。