Python实现下载界面(带进度条,断点续传,多线程多任务下载等)

开发环境:

Windows 7 64位,Python 3.6.2

实现功能:

进度条,下载速度和下载进度的显示,断点续传(暂停继续下载功能),取消下载等功能
下载界面,如图所示
Python实现下载界面(带进度条,断点续传,多线程多任务下载等)
点击'新建任务',弹出输入下载链接的窗口,如图所示
Python实现下载界面(带进度条,断点续传,多线程多任务下载等)
点击'开始下载',可以自动获取下载文件名和选择存储路径,如图所示:
Python实现下载界面(带进度条,断点续传,多线程多任务下载等)

关键代码:

因为断点续传是在之前的文件继续追加,所以open(filename,'ab')
这里打开文件的模式要为ab
实现断点续传的代码如下:

headers={'Range': 'bytes=%d-' %os.path.getsize(filename) }
r = requests.get(self.url,stream=True,headers=headers)
with open(filename, 'ab') as code:
    for chunk in r.iter_content(chunk_size=1024): #边下载边存硬盘
        if chunk :
            code.write(chunk)

显示进度条的代码(通过改变self.value的值显示下载进度,范围为0-100):

from tkinter import ttk
self.value=IntVar()
pb=ttk.Progressbar(self.fm4,length=200,variable=self.value)
pb.grid(row=0,column=1)

附上下载文件的关键代码:

import os
import requests
import time
import re
import urllib
class Getfile():  #下载文件
    def __init__(self,url):
        self.url=url
        self.flag=True  #当self.flag=False,暂停或取消下载,也就是结束下载线程
        self.header_flag=False #当为True时,设置header,断点续传
        self.re=requests.head(url,allow_redirects=True,timeout=20)  #运行head方法时重定向
    def getsize(self):
        try:
            self.file_total=int(self.re.headers['Content-Length']) #获取下载文件大小    
            return self.file_total
        except:
            return 0
    def getfilename(self):  #获取默认下载文件名
        if 'Content-Disposition' in self.re.headers:
            n=self.re.headers.get('Content-Disposition').split('name=')[1]
            filename=urllib.parse.unquote(n,encoding='utf8')
        else :
            filename=os.path.basename(self.re.url.split('?')[0])
        if filename=='':
            filename='index.html'
        return filename
    def downfile(self,filename):  #下载文件
        self.headers={}
        self.mode='wb'
        if os.path.exists(filename) and self.header_flag:
            self.headers={'Range': 'bytes=%d-' %os.path.getsize(filename) }
            self.mode='ab'
        self.r = requests.get(self.url,stream=True,headers=self.headers)
        with open(filename, self.mode) as code:
            for chunk in self.r.iter_content(chunk_size=1024): #边下载边存硬盘
                if chunk and self.flag:
                    code.write(chunk)
                else:
                    break
        time.sleep(1)
    def cancel(self,filename):  #取消下载
        self.flag=False
        time.sleep(1)
        if os.path.isfile(filename):
            os.remove(filename)

实现界面的代码有点多,这里就不给出来了。所有源码已经上传到 http://down.51cto.com/data/2445977 ,有需要的可以去下载。

思考与总结

在取消下载那里花了不少时间,一直在纠结着怎么强制退出下载文件的线程,最后发现不用强制退出,直接在下载文件的函数增加self.flag标志位,当为false时就可以使线程退出了。
这次的小项目又多学习到了多线程的一些知识。

猜你喜欢

转载自blog.51cto.com/eddy72/2106091