~tomasgroth/openlp/portable-path

« back to all changes in this revision

Viewing changes to openlp/core/common/httputils.py

  • Committer: Tomas Groth
  • Date: 2019-04-30 19:02:42 UTC
  • mfrom: (2829.2.32 openlp)
  • Revision ID: tomasgroth@yahoo.dk-20190430190242-6zwjk8724tyux70m
trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
###############################################################################
5
5
# OpenLP - Open Source Lyrics Projection                                      #
6
6
# --------------------------------------------------------------------------- #
7
 
# Copyright (c) 2008-2018 OpenLP Developers                                   #
 
7
# Copyright (c) 2008-2019 OpenLP Developers                                   #
8
8
# --------------------------------------------------------------------------- #
9
9
# This program is free software; you can redistribute it and/or modify it     #
10
10
# under the terms of the GNU General Public License as published by the Free  #
27
27
import sys
28
28
import time
29
29
from random import randint
 
30
from tempfile import gettempdir
30
31
 
31
32
import requests
 
33
from PyQt5 import QtCore
32
34
 
33
35
from openlp.core.common import trace_error_handler
 
36
from openlp.core.common.path import Path
34
37
from openlp.core.common.registry import Registry
35
38
from openlp.core.common.settings import ProxyMode, Settings
 
39
from openlp.core.threading import ThreadWorker
 
40
 
36
41
 
37
42
log = logging.getLogger(__name__ + '.__init__')
38
43
 
153
158
    return response.text
154
159
 
155
160
 
156
 
def get_url_file_size(url):
 
161
def get_url_file_size(url, proxy=None):
157
162
    """
158
163
    Get the size of a file.
159
164
 
160
165
    :param url: The URL of the file we want to download.
 
166
    :param dict | ProxyMode | None proxy: ProxyMode enum or a dictionary containing the proxy servers, with their types
 
167
        as the key e.g. {'http': 'http://proxyserver:port', 'https': 'https://proxyserver:port'}
161
168
    """
162
169
    retries = 0
 
170
    if not isinstance(proxy, dict):
 
171
        proxy = get_proxy_settings(mode=proxy)
163
172
    while True:
164
173
        try:
165
 
            response = requests.head(url, timeout=float(CONNECTION_TIMEOUT), allow_redirects=True)
 
174
            response = requests.head(url, proxies=proxy, timeout=float(CONNECTION_TIMEOUT), allow_redirects=True)
166
175
            return int(response.headers['Content-Length'])
167
176
        except OSError:
168
177
            if retries > CONNECTION_RETRIES:
173
182
                continue
174
183
 
175
184
 
176
 
def download_file(update_object, url, file_path, sha256=None):
 
185
def download_file(update_object, url, file_path, sha256=None, proxy=None):
177
186
    """"
178
187
    Download a file given a URL.  The file is retrieved in chunks, giving the ability to cancel the download at any
179
188
    point. Returns False on download error.
182
191
    :param url: URL to download
183
192
    :param file_path: Destination file
184
193
    :param sha256: The check sum value to be checked against the download value
 
194
    :param dict | ProxyMode | None proxy: ProxyMode enum or a dictionary containing the proxy servers, with their types
 
195
        as the key e.g. {'http': 'http://proxyserver:port', 'https': 'https://proxyserver:port'}
185
196
    """
186
197
    block_count = 0
187
198
    block_size = 4096
188
199
    retries = 0
 
200
    if not isinstance(proxy, dict):
 
201
        proxy = get_proxy_settings(mode=proxy)
189
202
    log.debug('url_get_file: %s', url)
190
203
    while retries < CONNECTION_RETRIES:
191
204
        try:
192
205
            with file_path.open('wb') as saved_file:
193
 
                response = requests.get(url, timeout=float(CONNECTION_TIMEOUT), stream=True)
 
206
                response = requests.get(url, proxies=proxy, timeout=float(CONNECTION_TIMEOUT), stream=True)
194
207
                if sha256:
195
208
                    hasher = hashlib.sha256()
196
209
                # Download until finished or canceled.
226
239
    return True
227
240
 
228
241
 
229
 
__all__ = ['get_web_page']
 
242
class DownloadWorker(ThreadWorker):
 
243
    """
 
244
    This worker allows a file to be downloaded in a thread
 
245
    """
 
246
    download_failed = QtCore.pyqtSignal()
 
247
    download_succeeded = QtCore.pyqtSignal(Path)
 
248
 
 
249
    def __init__(self, base_url, file_name):
 
250
        """
 
251
        Set up the worker object
 
252
        """
 
253
        self._base_url = base_url
 
254
        self._file_name = file_name
 
255
        self.was_cancelled = False
 
256
        super().__init__()
 
257
 
 
258
    def start(self):
 
259
        """
 
260
        Download the url to the temporary directory
 
261
        """
 
262
        if self.was_cancelled:
 
263
            self.quit.emit()
 
264
            return
 
265
        try:
 
266
            dest_path = Path(gettempdir()) / 'openlp' / self._file_name
 
267
            url = '{url}{name}'.format(url=self._base_url, name=self._file_name)
 
268
            is_success = download_file(self, url, dest_path)
 
269
            if is_success and not self.was_cancelled:
 
270
                self.download_succeeded.emit(dest_path)
 
271
            else:
 
272
                self.download_failed.emit()
 
273
        except Exception:
 
274
            log.exception('Unable to download %s', url)
 
275
            self.download_failed.emit()
 
276
        finally:
 
277
            self.quit.emit()
 
278
 
 
279
    @QtCore.pyqtSlot()
 
280
    def cancel_download(self):
 
281
        """
 
282
        A slot to allow the download to be cancelled from outside of the thread
 
283
        """
 
284
        self.was_cancelled = True