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 urllib2
import os import os
from base64 import encodestring from base64 import encodestring
from urllib import addinfourl
from shutil import move from shutil import move
import gettext import gettext
@@ -53,12 +54,14 @@ class Fetcher:
if not isinstance(url, URI): if not isinstance(url, URI):
url = URI(url) url = URI(url)
self.scheme = url.scheme()
self.url = url self.url = url
self.filedest = dest self.filedest = dest
util.check_dir(self.filedest) util.check_dir(self.filedest)
self.percent = 0 self.percent = 0
self.rate = 0.0 self.rate = 0.0
self.progress = None self.progress = None
self.existsize = 0
def fetch (self): def fetch (self):
"""Return value: Fetched file's full path..""" """Return value: Fetched file's full path.."""
@@ -69,27 +72,27 @@ class Fetcher:
if not os.access(self.filedest, os.W_OK): if not os.access(self.filedest, os.W_OK):
self.err(_("Access denied to write to dest dir")) 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(): if self.url.is_local_file():
self.fetchLocalFile(archiveFile + ".part") self.fetchLocalFile(archivefile + ".part")
else: else:
self.fetchRemoteFile(archiveFile + ".part") self.fetchRemoteFile(archivefile + ".part")
move(archiveFile + ".part", archiveFile) move(archivefile + ".part", archivefile)
return archiveFile return archivefile
def _do_grab(self, fileURI, dest, totalsize): def _do_grab(self, fileURI, dest, totalsize):
symbols = [' B/s', 'KB/s', 'MB/s', 'GB/s'] symbols = [' B/s', 'KB/s', 'MB/s', 'GB/s']
from time import time from time import time
tt, oldsize = int(time()), 0 tt, oldsize = int(time()), 0
bs, size = 1024, 0 bs, size = 1024, self.existsize
symbol, depth = "B/s", 0 symbol, depth = "B/s", 0
st = time() st = time()
chunk = fileURI.read(bs) chunk = fileURI.read(bs)
size = size + len(chunk) size = size + len(chunk)
if self.progress: if self.progress:
p = self.progress(totalsize) p = self.progress(totalsize, self.existsize)
self.percent = p.update(size) self.percent = p.update(size)
while chunk: while chunk:
dest.write(chunk) dest.write(chunk)
@@ -114,40 +117,46 @@ class Fetcher:
dest.close() dest.close()
def fetchLocalFile (self, archiveFile): def fetchLocalFile (self, archivefile):
url = self.url url = self.url
if not os.access(url.path(), os.F_OK): if not os.access(url.path(), os.F_OK):
self.err(_("No such file or no permission to read")) self.err(_("No such file or no permission to read"))
dest = open(archiveFile, "w") dest = open(archivefile, "w")
totalsize = os.path.getsize(url.path()) totalsize = os.path.getsize(url.path())
fileObj = open(url.path()) fileObj = open(url.path())
self._do_grab(fileObj, dest, totalsize) self._do_grab(fileObj, dest, totalsize)
def fetchRemoteFile (self, archiveFile): def fetchRemoteFile (self, archivefile):
from httplib import HTTPException 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 uri = self.url.uri
try: try:
fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri))) fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri)))
headers = fileObj.info() headers = fileObj.info()
except ValueError, e: 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: except IOError, e:
self.err('Cannot fetch %s; %s' % (uri, e)) self.err(_('Cannot fetch %s; %s') % (uri, e))
except OSError, e: except OSError, e:
self.err('Cannot fetch %s; %s' % (uri, e)) self.err(_('Cannot fetch %s; %s') % (uri, e))
except HTTPException, 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: try:
totalsize = int(headers['Content-Length']) totalsize = int(headers['Content-Length']) + self.existsize
except: except:
totalsize = 0 totalsize = 0
dest = open(archiveFile, "w")
self._do_grab(fileObj, dest, totalsize) self._do_grab(fileObj, dest, totalsize)
def formatRequest(self, request): def formatRequest(self, request):
@@ -155,8 +164,26 @@ class Fetcher:
if authinfo: if authinfo:
enc = encodestring("%s:%s" % authinfo) enc = encodestring("%s:%s" % authinfo)
request.add_header('Authorization', 'Basic %s' % enc) 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 return request
def err (self, error): def err (self, error):
raise Error(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 # generic user interface
# #
# Authors: Eray Ozkural <eray@uludag.org.tr> # Authors: Eray Ozkural <eray@uludag.org.tr>
# Murat Eren <meren@uludag.org.tr> # A. Murat Eren <meren@uludag.org.tr>
import sys import sys
@@ -23,9 +23,9 @@ class UI(object):
"Abstract class for UI operations, derive from this." "Abstract class for UI operations, derive from this."
class Progress: class Progress:
def __init__(self, totalsize): def __init__(self, totalsize, existsize = 0):
self.totalsize = totalsize self.totalsize = totalsize
self.percent = 0 self.percent = (existsize * 100) / totalsize
def update(self, size): def update(self, size):
if not self.totalsize: if not self.totalsize: