Skip to content

Instantly share code, notes, and snippets.

@akbargumbira
Last active August 29, 2015 13:57
Show Gist options
  • Save akbargumbira/9542300 to your computer and use it in GitHub Desktop.
Save akbargumbira/9542300 to your computer and use it in GitHub Desktop.
Improved fix temp
class Downloader(object):
"""The blueprint for downloading file from url."""
def __init__(self, manager, url, output_path, progress_dialog=None):
self.manager = manager
self.url = url
self.output_path = output_path
self.progress_dialog = progress_dialog
self.reply = None
self.output_file = None
self.downloaded_file_buffer = QByteArray()
self.is_finish = False
def download(self):
"""Downloading the file.
:returns: True if success, otherwise returns a tuple with format like
this (QNetworkReply.NetworkError, error_message)
:raises: IOError - when cannot create output_path
"""
# Prepare output path
self.output_file = QFile(self.output_path)
if not self.output_file.open(QFile.WriteOnly):
raise IOError(self.output_file.errorString())
# Request the url
request = QNetworkRequest(QUrl(self.url))
self.reply = self.manager.get(request)
self.reply.readyRead.connect(self.get_buffer)
self.reply.finished.connect(self.write_data)
if self.progress_dialog:
# progress bar
def progress_event(received, total):
"""Update progress.
:param received: Data received so far.
:type received: int
:param total: Total expected data.
:type total: int
"""
# noinspection PyArgumentList
QCoreApplication.processEvents()
label_text = "%s / %s" % (received, total)
self.progress_dialog.setLabelText(label_text)
self.progress_dialog.setMaximum(total)
self.progress_dialog.setValue(received)
# cancel
def cancel_action():
"""Cancel download."""
self.reply.abort()
self.reply.downloadProgress.connect(progress_event)
self.progress_dialog.canceled.connect(cancel_action)
# Wait until finished
# On Windows 32bit AND QGIS 2.2, self.reply.isFinished() always
# return False even after finished slot is called. So, that's why we
# are adding self.is_finish (see #864)
while not self.reply.isFinished() and not self.is_finish:
# noinspection PyArgumentList
QCoreApplication.processEvents()
result = self.reply.error()
if result == QNetworkReply.NoError:
return True, None
else:
return result, str(self.reply.errorString())
def get_buffer(self):
"""Get buffer from self.reply and store it to our buffer field."""
buffer_size = self.reply.size()
data = self.reply.read(buffer_size)
self.downloaded_file_buffer.append(data)
def write_data(self):
"""Write data to a file."""
self.output_file.write(self.downloaded_file_buffer)
self.output_file.close()
self.is_finish = True
def download_url(manager, url, output_path, progress_dialog=None):
"""Download file from url.
:param manager: A QNetworkAccessManager instance
:type manager: QNetworkAccessManager
:param url: URL of file
:type url: str
:param output_path: Output path
:type output_path: str
:param progress_dialog: Progress dialog widget
"""
downloader = Downloader(manager, url, output_path, progress_dialog)
try:
result = downloader.download()
except IOError as ex:
raise IOError(ex)
return result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment