mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUAC-963: Manage file downloads.
This commit is contained in:
		| @@ -559,67 +559,6 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams | ||||
|  | ||||
|     }; | ||||
|              | ||||
|     // Mapping of download stream index to notification object | ||||
|     var downloadNotifications = {}; | ||||
|      | ||||
|     // Mapping of download stream index to notification ID | ||||
|     var downloadNotificationIDs = {}; | ||||
|      | ||||
|     $scope.$on('guacClientFileDownloadStart', function handleClientFileDownloadStart(event, guacClient, streamIndex, mimetype, filename) { | ||||
|         $scope.$apply(function() { | ||||
|              | ||||
|             var notification = { | ||||
|                 className  : 'download', | ||||
|                 title      : 'CLIENT.DIALOG_TITLE_FILE_TRANSFER', | ||||
|                 text       : filename | ||||
|             }; | ||||
|              | ||||
|             downloadNotifications[streamIndex]   = notification; | ||||
|             downloadNotificationIDs[streamIndex] = $scope.addNotification(notification); | ||||
|              | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     $scope.$on('guacClientFileDownloadProgress', function handleClientFileDownloadProgress(event, guacClient, streamIndex, mimetype, filename, length) { | ||||
|         $scope.$apply(function() { | ||||
|              | ||||
|             var notification = downloadNotifications[streamIndex]; | ||||
|             if (notification) | ||||
|                 notification.progress = getFileProgress('CLIENT.TEXT_FILE_TRANSFER_PROGRESS', length); | ||||
|              | ||||
|         }); | ||||
|     }); | ||||
|      | ||||
|     $scope.$on('guacClientFileDownloadEnd', function handleClientFileDownloadEnd(event, guacClient, streamIndex, mimetype, filename, blob) { | ||||
|         $scope.$apply(function() { | ||||
|  | ||||
|             var notification = downloadNotifications[streamIndex]; | ||||
|             var notificationID = downloadNotificationIDs[streamIndex]; | ||||
|              | ||||
|             /** | ||||
|              * Saves the current file. | ||||
|              */ | ||||
|             var saveFile = function saveFile() { | ||||
|                 saveAs(blob, filename); | ||||
|                 $scope.removeNotification(notificationID); | ||||
|                 delete downloadNotifications[streamIndex]; | ||||
|                 delete downloadNotificationIDs[streamIndex]; | ||||
|             }; | ||||
|              | ||||
|             // Add download action and remove progress indicator | ||||
|             if (notificationID && notification) { | ||||
|                 delete notification.progress; | ||||
|                 notification.actions = [ | ||||
|                     { | ||||
|                         name       : 'CLIENT.ACTION_SAVE_FILE', | ||||
|                         callback   : saveFile | ||||
|                     } | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     // Clean up when view destroyed | ||||
|     $scope.$on('$destroy', function clientViewDestroyed() { | ||||
|  | ||||
|   | ||||
| @@ -27,10 +27,11 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', | ||||
|     function defineManagedClient($rootScope, $injector) { | ||||
|  | ||||
|     // Required types | ||||
|     var ClientProperties   = $injector.get('ClientProperties'); | ||||
|     var ManagedClientState = $injector.get('ManagedClientState'); | ||||
|     var ManagedDisplay     = $injector.get('ManagedDisplay'); | ||||
|     var ManagedFileUpload  = $injector.get('ManagedFileUpload'); | ||||
|     var ClientProperties     = $injector.get('ClientProperties'); | ||||
|     var ManagedClientState   = $injector.get('ManagedClientState'); | ||||
|     var ManagedDisplay       = $injector.get('ManagedDisplay'); | ||||
|     var ManagedFileDownload  = $injector.get('ManagedFileDownload'); | ||||
|     var ManagedFileUpload    = $injector.get('ManagedFileUpload'); | ||||
|  | ||||
|     // Required services | ||||
|     var $window                = $injector.get('$window'); | ||||
| @@ -100,6 +101,15 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', | ||||
|          */ | ||||
|         this.clipboardData = template.clipboardData; | ||||
|  | ||||
|         /** | ||||
|          * All downloaded files. As files are downloaded, their progress can be | ||||
|          * observed through the elements of this array. It is intended that | ||||
|          * this array be manipulated externally as needed. | ||||
|          * | ||||
|          * @type ManagedFileDownload[] | ||||
|          */ | ||||
|         this.downloads = template.downloads || []; | ||||
|  | ||||
|         /** | ||||
|          * All uploaded files. As files are uploaded, their progress can be | ||||
|          * observed through the elements of this array. It is intended that | ||||
| @@ -366,43 +376,16 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         // Handle any received files | ||||
|         client.onfile = function clientFileReceived(stream, mimetype, filename) { | ||||
|             $rootScope.$apply(function startDownload() { | ||||
|                 managedClient.downloads.push(ManagedFileDownload.getInstance(stream, mimetype, filename)); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         // Manage the client display | ||||
|         managedClient.managedDisplay = ManagedDisplay.getInstance(client.getDisplay()); | ||||
|  | ||||
|         /* TODO: Restore file transfer again */ | ||||
|  | ||||
|         /* | ||||
|         // Handle any received files | ||||
|         client.onfile = function onClientFile(stream, mimetype, filename) { | ||||
|  | ||||
|             // Begin file download | ||||
|             var guacFileStartEvent = $rootScope.$emit('guacClientFileDownloadStart', client, stream.index, mimetype, filename); | ||||
|             if (!guacFileStartEvent.defaultPrevented) { | ||||
|  | ||||
|                 var blob_reader = new Guacamole.BlobReader(stream, mimetype); | ||||
|  | ||||
|                 // Update progress as data is received | ||||
|                 blob_reader.onprogress = function onprogress() { | ||||
|                     $rootScope.$emit('guacClientFileDownloadProgress', client, stream.index, mimetype, filename, blob_reader.getLength()); | ||||
|                     stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); | ||||
|                 }; | ||||
|  | ||||
|                 // When complete, prompt for download | ||||
|                 blob_reader.onend = function onend() { | ||||
|                     $rootScope.$emit('guacClientFileDownloadEnd', client, stream.index, mimetype, filename, blob_reader.getBlob()); | ||||
|                 }; | ||||
|  | ||||
|                 stream.sendAck("Ready", Guacamole.Status.Code.SUCCESS); | ||||
|                  | ||||
|             } | ||||
|              | ||||
|             // Respond with UNSUPPORTED if download (default action) canceled within event handler | ||||
|             else | ||||
|                 stream.sendAck("Download canceled", Guacamole.Status.Code.UNSUPPORTED); | ||||
|  | ||||
|         }; | ||||
|         */ | ||||
|  | ||||
|         // Connect the Guacamole client | ||||
|         client.connect(getConnectString(id, connectionParameters)); | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,153 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Provides the ManagedFileDownload class used by the guacClientManager service. | ||||
|  */ | ||||
| angular.module('client').factory('ManagedFileDownload', ['$rootScope', '$injector', | ||||
|     function defineManagedFileDownload($rootScope, $injector) { | ||||
|  | ||||
|     // Required types | ||||
|     var ManagedFileTransferState = $injector.get('ManagedFileTransferState'); | ||||
|  | ||||
|     /** | ||||
|      * Object which serves as a surrogate interface, encapsulating a Guacamole | ||||
|      * file download while it is active, allowing it to be detached and | ||||
|      * reattached from different client views. | ||||
|      *  | ||||
|      * @constructor | ||||
|      * @param {ManagedFileDownload|Object} [template={}] | ||||
|      *     The object whose properties should be copied within the new | ||||
|      *     ManagedFileDownload. | ||||
|      */ | ||||
|     var ManagedFileDownload = function ManagedFileDownload(template) { | ||||
|  | ||||
|         // Use empty object by default | ||||
|         template = template || {}; | ||||
|  | ||||
|         /** | ||||
|          * The current state of the file transfer stream. | ||||
|          * | ||||
|          * @type ManagedFileTransferState | ||||
|          */ | ||||
|         this.transferState = template.transferState || new ManagedFileTransferState(); | ||||
|  | ||||
|         /** | ||||
|          * The mimetype of the file being transferred. | ||||
|          * | ||||
|          * @type String | ||||
|          */ | ||||
|         this.mimetype = template.mimetype; | ||||
|  | ||||
|         /** | ||||
|          * The filename of the file being transferred. | ||||
|          * | ||||
|          * @type String | ||||
|          */ | ||||
|         this.filename = template.filename; | ||||
|  | ||||
|         /** | ||||
|          * The number of bytes transferred so far. | ||||
|          * | ||||
|          * @type Number | ||||
|          */ | ||||
|         this.progress = template.progress; | ||||
|  | ||||
|         /** | ||||
|          * A blob containing the complete downloaded file. This is available | ||||
|          * only after the download has finished. | ||||
|          * | ||||
|          * @type Blob | ||||
|          */ | ||||
|         this.blob = template.blob; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Creates a new ManagedFileDownload which downloads the contents of the | ||||
|      * given stream as a file having the given mimetype and filename. | ||||
|      * | ||||
|      * @param {Guacamole.InputStream} stream | ||||
|      *     The stream whose contents should be downloaded as a file. | ||||
|      * | ||||
|      * @param {String} mimetype | ||||
|      *     The mimetype of the stream contents. | ||||
|      * | ||||
|      * @param {String} filename | ||||
|      *     The filename of the file being received over the steram. | ||||
|      * | ||||
|      * @return {ManagedFileDownload} | ||||
|      *     A new ManagedFileDownload object which can be used to track the | ||||
|      *     progress of the download. | ||||
|      */ | ||||
|     ManagedFileDownload.getInstance = function getInstance(stream, mimetype, filename) { | ||||
|  | ||||
|         // Init new file download object | ||||
|         var managedFileDownload = new ManagedFileDownload({ | ||||
|             mimetype : mimetype, | ||||
|             filename : filename, | ||||
|             progress : 0, | ||||
|             transferState : new ManagedFileTransferState({ | ||||
|                 streamState : ManagedFileTransferState.StreamState.OPEN | ||||
|             }) | ||||
|         }); | ||||
|  | ||||
|         // Begin file download | ||||
|         var blob_reader = new Guacamole.BlobReader(stream, mimetype); | ||||
|  | ||||
|         // Update progress as data is received | ||||
|         blob_reader.onprogress = function onprogress() { | ||||
|  | ||||
|             // Update progress | ||||
|             $rootScope.$apply(function downloadStreamProgress() { | ||||
|                 managedFileDownload.progress = blob_reader.getLength(); | ||||
|             }); | ||||
|  | ||||
|             // Signal server that data was received | ||||
|             stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         // Save blob and close stream when complete | ||||
|         blob_reader.onend = function onend() { | ||||
|             $rootScope.$apply(function downloadStreamEnd() { | ||||
|  | ||||
|                 // Save blob | ||||
|                 managedFileDownload.blob = blob_reader.getBlob(); | ||||
|  | ||||
|                 // Mark stream as closed | ||||
|                 ManagedFileTransferState.setStreamState(managedFileDownload.transferState, | ||||
|                     ManagedFileTransferState.StreamState.CLOSED); | ||||
|  | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         // Signal server that data is ready to be received | ||||
|         stream.sendAck("Ready", Guacamole.Status.Code.SUCCESS); | ||||
|          | ||||
|         return managedFileDownload; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     return ManagedFileDownload; | ||||
|  | ||||
| }]); | ||||
		Reference in New Issue
	
	Block a user