http ve https için resume desteği..

test ediniz.
This commit is contained in:
A. Murat Eren
2005-10-12 11:53:22 +00:00
parent bb37cb7cb1
commit 757b3d77b0
2 changed files with 47 additions and 20 deletions
+44 -17
View File
@@ -19,6 +19,7 @@
import urllib2
import os
from base64 import encodestring
from urllib import addinfourl
from shutil import move
import gettext
@@ -53,12 +54,14 @@ class Fetcher:
if not isinstance(url, URI):
url = URI(url)
self.scheme = url.scheme()
self.url = url
self.filedest = dest
util.check_dir(self.filedest)
self.percent = 0
self.rate = 0.0
self.progress = None
self.existsize = 0
def fetch (self):
"""Return value: Fetched file's full path.."""
@@ -69,27 +72,27 @@ class Fetcher:
if not os.access(self.filedest, os.W_OK):
self.err(_("Access denied to write to dest dir"))
archiveFile = os.path.join(self.filedest, self.url.filename())
archivefile = os.path.join(self.filedest, self.url.filename())
if self.url.is_local_file():
self.fetchLocalFile(archiveFile + ".part")
self.fetchLocalFile(archivefile + ".part")
else:
self.fetchRemoteFile(archiveFile + ".part")
self.fetchRemoteFile(archivefile + ".part")
move(archiveFile + ".part", archiveFile)
return archiveFile
move(archivefile + ".part", archivefile)
return archivefile
def _do_grab(self, fileURI, dest, totalsize):
symbols = [' B/s', 'KB/s', 'MB/s', 'GB/s']
from time import time
tt, oldsize = int(time()), 0
bs, size = 1024, 0
bs, size = 1024, self.existsize
symbol, depth = "B/s", 0
st = time()
chunk = fileURI.read(bs)
size = size + len(chunk)
if self.progress:
p = self.progress(totalsize)
p = self.progress(totalsize, self.existsize)
self.percent = p.update(size)
while chunk:
dest.write(chunk)
@@ -114,40 +117,46 @@ class Fetcher:
dest.close()
def fetchLocalFile (self, archiveFile):
def fetchLocalFile (self, archivefile):
url = self.url
if not os.access(url.path(), os.F_OK):
self.err(_("No such file or no permission to read"))
dest = open(archiveFile, "w")
dest = open(archivefile, "w")
totalsize = os.path.getsize(url.path())
fileObj = open(url.path())
self._do_grab(fileObj, dest, totalsize)
def fetchRemoteFile (self, archiveFile):
def fetchRemoteFile (self, archivefile):
from httplib import HTTPException
if os.path.exists(archivefile) and \
self.scheme == "http" or self.scheme == "https":
self.existsize = os.path.getsize(archivefile)
dest = open(archivefile, "ab")
else:
dest = open(archivefile, "wb")
uri = self.url.uri
try:
fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri)))
headers = fileObj.info()
except ValueError, e:
self.err('Cannot fetch %s; value error: %s' % (uri, e))
self.err(_('Cannot fetch %s; value error: %s') % (uri, e))
except IOError, e:
self.err('Cannot fetch %s; %s' % (uri, e))
self.err(_('Cannot fetch %s; %s') % (uri, e))
except OSError, e:
self.err('Cannot fetch %s; %s' % (uri, e))
self.err(_('Cannot fetch %s; %s') % (uri, e))
except HTTPException, e:
self.err(('Cannot fetch %s; (%s): %s') % (uri, e.__class__.__name__, e))
self.err(_('Cannot fetch %s; (%s): %s') % (uri, e.__class__.__name__, e))
try:
totalsize = int(headers['Content-Length'])
totalsize = int(headers['Content-Length']) + self.existsize
except:
totalsize = 0
dest = open(archiveFile, "w")
self._do_grab(fileObj, dest, totalsize)
def formatRequest(self, request):
@@ -155,8 +164,26 @@ class Fetcher:
if authinfo:
enc = encodestring("%s:%s" % authinfo)
request.add_header('Authorization', 'Basic %s' % enc)
if self.existsize and self.scheme == "http" or self.scheme == "https":
range_handler = HTTPRangeHandler()
opener = urllib2.build_opener(range_handler)
urllib2.install_opener(opener)
request.add_header('Range', 'bytes=%d-' % self.existsize)
return request
def err (self, error):
raise Error(error)
class HTTPRangeHandler(urllib2.BaseHandler):
"""
"to override the urllib2 error: 'Error 206: Partial Content'
this reponse from the HTTP server is already what we expected to get.
Don't give up, resume downloading..
"""
def http_error_206(self, request, fp, errcode, msg, headers):
return addinfourl(fp, headers, request.get_full_url())
def http_error_416(self, request, fp, errcode, msg, headers):
# HTTP 1.1's 'Range Not Satisfiable' error..
raise FetchError(_('Requested range not satisfiable'))
+3 -3
View File
@@ -12,7 +12,7 @@
# generic user interface
#
# Authors: Eray Ozkural <eray@uludag.org.tr>
# Murat Eren <meren@uludag.org.tr>
# A. Murat Eren <meren@uludag.org.tr>
import sys
@@ -23,9 +23,9 @@ class UI(object):
"Abstract class for UI operations, derive from this."
class Progress:
def __init__(self, totalsize):
def __init__(self, totalsize, existsize = 0):
self.totalsize = totalsize
self.percent = 0
self.percent = (existsize * 100) / totalsize
def update(self, size):
if not self.totalsize: