http ve https için resume desteği..
test ediniz.
This commit is contained in:
+44
-17
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user