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