diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 35f8d95ca6..0a2d406d59 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -17,7 +17,7 @@ from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope -from PyQt5.QtNetwork import QNetworkReply +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest from .UploadBackupJob import UploadBackupJob from .Settings import Settings @@ -30,6 +30,7 @@ catalog = i18nCatalog("cura") @signalemitter class DriveApiService: BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) + DISK_WRITE_BUFFER_SIZE = 512 * 1024 # Emit signal when restoring backup started or finished. restoringStateChanged = Signal() @@ -40,9 +41,14 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + self._in_progress_backup = None def getBackups(self, changed: Callable): - def callback(reply: QNetworkReply): + def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): + if error is not None: + Logger.log("w", "Could not get backups: " + str(error)) + changed([]) + backup_list_response = HttpRequestManager.readJSON(reply) if "data" not in backup_list_response: Logger.log("w", "Could not get backups from remote, actual response body was: %s", @@ -94,22 +100,32 @@ class DriveApiService: # If there is no download URL, we can't restore the backup. return self._emitRestoreError() - try: - download_package = requests.get(download_url, stream = True) - except requests.exceptions.ConnectionError: - Logger.logException("e", "Unable to connect with the server") - return self._emitRestoreError() + def finishedCallback(reply: QNetworkReply, bu=backup) -> None: + self._onRestoreRequestCompleted(reply, None, bu) - if download_package.status_code >= 300: - # Something went wrong when attempting to download the backup. - Logger.log("w", "Could not download backup from url %s: %s", download_url, download_package.text) - return self._emitRestoreError() + HttpRequestManager.getInstance().get( + url = download_url, + callback = finishedCallback, + error_callback = self._onRestoreRequestCompleted + ) + + def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, backup = None): + if error is not None or reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: + Logger.log("w", + "Requesting backup failed, response code %s while trying to connect to %s", + reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) + self._emitRestoreError() + return # We store the file in a temporary path fist to ensure integrity. temporary_backup_file = NamedTemporaryFile(delete = False) with open(temporary_backup_file.name, "wb") as write_backup: - for chunk in download_package: - write_backup.write(chunk) + app = CuraApplication.getInstance() + bytes_read = reply.read(DriveApiService.DISK_WRITE_BUFFER_SIZE) + while bytes_read: + write_backup.write(bytes_read) + bytes_read = reply.read(DriveApiService.DISK_WRITE_BUFFER_SIZE) + app.processEvents() if not self._verifyMd5Hash(temporary_backup_file.name, backup.get("md5_hash", "")): # Don't restore the backup if the MD5 hashes do not match.