function FileReader() {

		RuntimeClient.call(this);

		Basic.extend(this, {
			/**
			UID of the component instance.

			@property uid
			@type {String}
			*/
			uid: Basic.guid('uid_'),

			/**
			Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING
			and FileReader.DONE.

			@property readyState
			@type {Number}
			@default FileReader.EMPTY
			*/
			readyState: FileReader.EMPTY,
			
			/**
			Result of the successful read operation.

			@property result
			@type {String}
			*/
			result: null,
			
			/**
			Stores the error of failed asynchronous read operation.

			@property error
			@type {DOMError}
			*/
			error: null,
			
			/**
			Initiates reading of File/Blob object contents to binary string.

			@method readAsBinaryString
			@param {Blob|File} blob Object to preload
			*/
			readAsBinaryString: function(blob) {
				_read.call(this, 'readAsBinaryString', blob);
			},
			
			/**
			Initiates reading of File/Blob object contents to dataURL string.

			@method readAsDataURL
			@param {Blob|File} blob Object to preload
			*/
			readAsDataURL: function(blob) {
				_read.call(this, 'readAsDataURL', blob);
			},
			
			/**
			Initiates reading of File/Blob object contents to string.

			@method readAsText
			@param {Blob|File} blob Object to preload
			*/
			readAsText: function(blob) {
				_read.call(this, 'readAsText', blob);
			},
			
			/**
			Aborts preloading process.

			@method abort
			*/
			abort: function() {
				this.result = null;
				
				if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) {
					return;
				} else if (this.readyState === FileReader.LOADING) {
					this.readyState = FileReader.DONE;
				}

				this.exec('FileReader', 'abort');
				
				this.trigger('abort');
				this.trigger('loadend');
			},

			/**
			Destroy component and release resources.

			@method destroy
			*/
			destroy: function() {
				this.abort();
				this.exec('FileReader', 'destroy');
				this.disconnectRuntime();
				this.unbindAll();
			}
		});

		// uid must already be assigned
		this.handleEventProps(dispatches);

		this.bind('Error', function(e, err) {
			this.readyState = FileReader.DONE;
			this.error = err;
		}, 999);
		
		this.bind('Load', function(e) {
			this.readyState = FileReader.DONE;
		}, 999);

		
		function _read(op, blob) {
			var self = this;			

			this.trigger('loadstart');

			if (this.readyState === FileReader.LOADING) {
				this.trigger('error', new x.DOMException(x.DOMException.INVALID_STATE_ERR));
				this.trigger('loadend');
				return;
			}

			// if source is not o.Blob/o.File
			if (!(blob instanceof Blob)) {
				this.trigger('error', new x.DOMException(x.DOMException.NOT_FOUND_ERR));
				this.trigger('loadend');
				return;
			}

			this.result = null;
			this.readyState = FileReader.LOADING;
			
			if (blob.isDetached()) {
				var src = blob.getSource();
				switch (op) {
					case 'readAsText':
					case 'readAsBinaryString':
						this.result = src;
						break;
					case 'readAsDataURL':
						this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src);
						break;
				}
				this.readyState = FileReader.DONE;
				this.trigger('load');
				this.trigger('loadend');
			} else {
				this.connectRuntime(blob.ruid);
				this.exec('FileReader', 'read', op, blob);
			}
		}
	}
Dispatched when the request has completed (either in success or failure).

		@event loadend
		@param {Object} event