下面是对于“python支持断点续传的多线程下载示例”的完整攻略:
背景介绍
在进行大文件下载时,常常需要使用多线程进行下载加速,但是在下载过程中,如果意外终止了下载,那么就需要重新下载。这时候,我们可以使用断点续传的功能,可以在下载被中断后从上次下载的位置继续进行下载。
示例1:使用urllib库实现断点续传
import urllib.request
import os
class Download:
    def __init__(self, url):
        self.url = url
        self.downloaded = 0
        self.total = 0
        self.filename = url.split("/")[-1]
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0;Win64) AppleWebkit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299",
            "Range": "bytes=0-",
        }
    def get_total(self):
        req = urllib.request.Request(self.url, headers=self.headers)
        res = urllib.request.urlopen(req)
        content_range = res.headers.get("Content-Range")
        if content_range:
            self.total = int(content_range.split("/")[-1])
        else:
            self.total = int(res.headers.get("Content-Length"))
    def download(self, start=0):
        self.headers["Range"] = "bytes=%d-" % start
        req = urllib.request.Request(self.url, headers=self.headers)
        res = urllib.request.urlopen(req)
        with open(self.filename, "ab") as f:
            while True:
                chunk = res.read(1024*50)
                if not chunk:
                    break
                f.write(chunk)
                self.downloaded += len(chunk)
            f.flush()
def main():
    url = "http://speedtest.ftp.otenet.gr/files/test100Mb.db"
    d = Download(url)
    d.get_total()
    if os.path.exists(d.filename):
        d.downloaded = os.path.getsize(d.filename)
    print("total:", d.total)
    print("downloaded:", d.downloaded)
    d.download(d.downloaded)
if __name__ == "__main__":
    main()
这段代码使用了urllib库,可以在下载过程中实现断点续传。首先获取文件总大小,然后在下载过程中根据已经下载的文件大小设置http请求的Range请求头,就能够实现从断点处继续进行下载了。需要注意的是,在下载过程中需要将数据追加写入文件而不是覆盖原有文件。
示例2:使用requests库实现断点续传
import requests
import os
class Download:
    def __init__(self, url):
        self.url = url
        self.downloaded = 0
        self.total = 0
        self.filename = url.split("/")[-1]
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0;Win64) AppleWebkit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299",
            "Range": "bytes=0-",
        }
    def get_total(self):
        res = requests.head(self.url)
        content_range = res.headers.get("Content-Range")
        if content_range:
            self.total = int(content_range.split("/")[-1])
        else:
            self.total = int(res.headers.get("Content-Length"))
    def download(self, start=0):
        self.headers["Range"] = "bytes=%d-" % start
        res = requests.get(self.url, headers=self.headers, stream=True)
        with open(self.filename, "ab") as f:
            for chunk in res.iter_content(1024*50):
                if chunk:
                    f.write(chunk)
                    self.downloaded += len(chunk)
            f.flush()
def main():
    url = "http://speedtest.ftp.otenet.gr/files/test100Mb.db"
    d = Download(url)
    d.get_total()
    if os.path.exists(d.filename):
        d.downloaded = os.path.getsize(d.filename)
    print("total:", d.total)
    print("downloaded:", d.downloaded)
    d.download(d.downloaded)
if __name__ == "__main__":
    main()
这段代码使用了requests库,同样可以实现断点续传的效果。类似于上面的方法,首先获取文件总大小,同时根据已经下载的文件大小设置http请求的Range请求头。另外,需要使用stream=True参数来启用流式下载,从而避免将文件全部加载进内存导致内存使用过多。同样需要注意的是,下载过程中需要将数据追加写入文件而不是覆盖原有文件。
以上是两种实现方法。需要注意的是,在进行下载时要确保文件名存在且文件名唯一,否则可能会出现文件覆盖或者文件内容错误等问题。另外,对于下载速度等问题也需要进行合理配置,避免对服务器或者网络造成过大的负担。
The End


大气响应式网络建站服务公司织梦模板
高端大气html5设计公司网站源码
织梦dede网页模板下载素材销售下载站平台(带会员中心带筛选)
财税代理公司注册代理记账网站织梦模板(带手机端)
成人高考自考在职研究生教育机构网站源码(带手机端)
高端HTML5响应式企业集团通用类网站织梦模板(自适应手机端)