GUACAMOLE-44: Use Guacamole.FileWriter within ManagedFileUpload (rather than load entire file into memory).

This commit is contained in:
Michael Jumper
2016-06-02 15:51:15 -07:00
parent 998eff9ca3
commit 2934f4a9be

View File

@@ -29,16 +29,6 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector'
// Required services
var $window = $injector.get('$window');
/**
* The maximum number of bytes to include in each blob for the Guacamole
* file stream. Note that this, along with instruction opcode and protocol-
* related overhead, must not exceed the 8192 byte maximum imposed by the
* Guacamole protocol.
*
* @type Number
*/
var STREAM_BLOB_SIZE = 4096;
/**
* Object which serves as a surrogate interface, encapsulating a Guacamole
* file upload while it is active, allowing it to be detached and
@@ -136,10 +126,7 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector'
ManagedFileUpload.getInstance = function getInstance(client, file, object, streamName) {
var managedFileUpload = new ManagedFileUpload();
// Construct reader for file
var reader = new FileReader();
reader.onloadend = function fileContentsLoaded() {
var streamAcknowledged = false;
// Open file for writing
var stream;
@@ -151,17 +138,14 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector'
else
stream = object.createOutputStream(file.type, streamName);
var valid = true;
var bytes = new Uint8Array(reader.result);
var offset = 0;
// Notify that the file transfer is pending
$rootScope.$apply(function uploadStreamOpen() {
// Init managed upload
managedFileUpload.filename = file.name;
managedFileUpload.mimetype = file.type;
managedFileUpload.progress = 0;
managedFileUpload.length = bytes.length;
managedFileUpload.length = file.size;
// Notify that stream is open
ManagedFileTransferState.setStreamState(managedFileUpload.transferState,
@@ -169,13 +153,13 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector'
});
// Invalidate stream on all errors
// Continue upload when acknowledged
stream.onack = function ackReceived(status) {
var writer = new Guacamole.FileWriter(stream);
// Handle errors
// Begin upload when stream is acknowledged, notify of any errors
writer.onack = function ackReceived(status) {
// Notify of any errors from the Guacamole server
if (status.isError()) {
valid = false;
$rootScope.$apply(function uploadStreamError() {
ManagedFileTransferState.setStreamState(managedFileUpload.transferState,
ManagedFileTransferState.StreamState.ERROR,
@@ -183,26 +167,41 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector'
});
}
// Abort upload if stream is invalid
if (!valid)
return false;
// Begin sending the requested file once stream is acknowledged
else if (!streamAcknowledged) {
writer.sendFile(file);
streamAcknowledged = true;
}
// Encode packet as base64
var slice = bytes.subarray(offset, offset + STREAM_BLOB_SIZE);
var base64 = getBase64(slice);
};
// Write packet
stream.sendBlob(base64);
// Abort and notify if the file cannot be read
writer.onerror = function fileReadError(file, offset, error) {
// Advance to next packet
offset += STREAM_BLOB_SIZE;
// Abort transfer
writer.sendEnd();
// Upload failed
ManagedFileTransferState.setStreamState(managedFileUpload.transferState,
ManagedFileTransferState.StreamState.ERROR);
};
// Notify of upload progress
writer.onprogress = function uploadProgressing(file, length) {
$rootScope.$apply(function uploadStreamProgress() {
managedFileUpload.progress = length;
});
};
// Clean up and notify when upload completes
writer.oncomplete = function uploadComplete(file) {
// If at end, stop upload
if (offset >= bytes.length) {
stream.sendEnd();
managedFileUpload.progress = bytes.length;
writer.sendEnd();
managedFileUpload.progress = file.size;
// Upload complete
ManagedFileTransferState.setStreamState(managedFileUpload.transferState,
@@ -211,18 +210,7 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector'
// Notify of upload completion
$rootScope.$broadcast('guacUploadComplete', file.name);
}
// Otherwise, update progress
else
managedFileUpload.progress = offset;
});
}; // end ack handler
};
reader.readAsArrayBuffer(file);
return managedFileUpload;