From c6c120b9aa3b081fc9724f083b72bfc7f83ebce7 Mon Sep 17 00:00:00 2001 From: timb Date: Thu, 11 Feb 2010 03:54:41 -0800 Subject: enabled webcam upload\! --- webcam/Webcam.as | 2 +- webcam/com/marstonstudio/UploadPostHelper.as | 21 +- webcam/ru/inspirit/net/MultipartURLLoader.as | 582 --------------------- .../inspirit/net/events/MultipartURLLoaderEvent.as | 27 - 4 files changed, 13 insertions(+), 619 deletions(-) delete mode 100644 webcam/ru/inspirit/net/MultipartURLLoader.as delete mode 100644 webcam/ru/inspirit/net/events/MultipartURLLoaderEvent.as (limited to 'webcam') diff --git a/webcam/Webcam.as b/webcam/Webcam.as index c8be6ca..7a55373 100644 --- a/webcam/Webcam.as +++ b/webcam/Webcam.as @@ -1 +1 @@ -package { /* JPEGCam v1.0.8 */ /* Webcam library for capturing JPEG images and submitting to a server */ /* Copyright (c) 2008 - 2009 Joseph Huckaby */ /* Licensed under the GNU Lesser Public License */ /* http://www.gnu.org/licenses/lgpl.html */ import flash.display.LoaderInfo; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.display.Bitmap; import flash.display.BitmapData; import flash.events.*; import flash.utils.*; import flash.media.Camera; import flash.media.Video; import flash.external.ExternalInterface; import flash.net.*; import flash.system.Security; import flash.system.SecurityPanel; import flash.media.Sound; import flash.media.SoundChannel; import flash.geom.Matrix; import com.adobe.images.JPGEncoder; public class Webcam extends Sprite { private var video:Video; private var encoder:JPGEncoder; private var snd:Sound; private var channel:SoundChannel = new SoundChannel(); private var jpeg_quality:int; private var video_width:int; private var video_height:int; private var server_width:int; private var server_height:int; private var camera:Camera; private var bmp:Bitmap; private var bmpdata:BitmapData; private var url:String; public function Webcam() { // class constructor flash.system.Security.allowDomain("*"); var flashvars:Object = LoaderInfo(this.root.loaderInfo).parameters; video_width = Math.floor( flashvars.width ); video_height = Math.floor( flashvars.height ); server_width = Math.floor( flashvars.server_width ); server_height = Math.floor( flashvars.server_height ); stage.scaleMode = StageScaleMode.NO_SCALE; // stage.scaleMode = StageScaleMode.EXACT_FIT; stage.align = StageAlign.TOP_LEFT; stage.stageWidth = Math.max(video_width, server_width); stage.stageHeight = Math.max(video_height, server_height); // Hack to auto-select iSight camera on Mac (JPEGCam Issue #5, submitted by manuel.gonzalez.noriega) // From: http://www.squidder.com/2009/03/09/trick-auto-select-mac-isight-in-flash/ var cameraIdx:int = -1; for (var idx = 0, len = Camera.names.length; idx < len; idx++) { if (Camera.names[idx] == "USB Video Class Video") { cameraIdx = idx; idx = len; } } if (cameraIdx > -1) camera = Camera.getCamera( String(cameraIdx) ); else camera = Camera.getCamera(); if (camera != null) { camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler); video = new Video( Math.max(video_width, server_width), Math.max(video_height, server_height) ); video.attachCamera(camera); addChild(video); if ((video_width < server_width) && (video_height < server_height)) { video.scaleX = video_width / server_width; video.scaleY = video_height / server_height; } camera.setQuality(0, 100); camera.setKeyFrameInterval(10); camera.setMode( Math.max(video_width, server_width), Math.max(video_height, server_height), 30); // do not detect motion (may help reduce CPU usage) camera.setMotionLevel( 100 ); ExternalInterface.addCallback('_snap', snap); ExternalInterface.addCallback('_configure', configure); ExternalInterface.addCallback('_upload', upload); ExternalInterface.addCallback('_reset', reset); if (flashvars.shutter_enabled == 1) { snd = new Sound(); snd.load( new URLRequest( flashvars.shutter_url ) ); } jpeg_quality = 90; ExternalInterface.call('webcam.flash_notify', 'flashLoadComplete', true); } else { trace("You need a camera."); ExternalInterface.call('webcam.flash_notify', "error", "No camera was detected."); } } public function set_quality(new_quality:int) { // set JPEG image quality if (new_quality < 0) new_quality = 0; if (new_quality > 100) new_quality = 100; jpeg_quality = new_quality; } public function configure(panel:String = SecurityPanel.CAMERA) { // show configure dialog inside flash movie Security.showSettings(panel); } private function activityHandler(event:ActivityEvent):void { trace("activityHandler: " + event); } public function snap(url, new_quality, shutter) { // take snapshot from camera, and upload if URL was provided if (new_quality) set_quality(new_quality); trace("in snap(), drawing to bitmap"); if (shutter) { channel = snd.play(); setTimeout( snap2, 10, url ); } else snap2(url); } public function snap2(url) { // take snapshot, convert to jpeg, submit to server bmpdata = new BitmapData( Math.max(video_width, server_width), Math.max(video_height, server_height) ); bmpdata.draw( video ); // draw snapshot on stage bmp = new Bitmap( bmpdata ); addChild( bmp ); // stop capturing video video.attachCamera( null ); removeChild( video ); // if URL was provided, upload now if (url) upload( url ); } public function upload(url) { if (bmpdata) { if ((video_width > server_width) && (video_height > server_height)) { // resize image downward before submitting var tmpdata = new BitmapData(server_width, server_height); var matrix = new Matrix(); matrix.scale( server_width / video_width, server_height / video_height ); tmpdata.draw( bmpdata, matrix, null, null, null, true ); // smoothing bmpdata = tmpdata; } // need resize trace("converting to jpeg"); var ba:ByteArray; encoder = new JPGEncoder( jpeg_quality ); ba = encoder.encode( bmpdata ); trace("jpeg length: " + ba.length); var head:URLRequestHeader = new URLRequestHeader("Accept","text/*"); var req:URLRequest = new URLRequest( url ); req.requestHeaders.push(head); req.data = ba; req.method = URLRequestMethod.POST; req.contentType = "image/jpeg"; var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onLoaded); trace("sending post to: " + url); try { loader.load(req); } catch (error:Error) { trace("Unable to load requested document."); ExternalInterface.call('webcam.flash_notify', "error", "Unable to post data: " + error); } } else { ExternalInterface.call('webcam.flash_notify', "error", "Nothing to upload, must capture an image first."); } } public function onLoaded(evt:Event):void { // image upload complete var msg = "unknown"; if (evt && evt.target && evt.target.data) msg = evt.target.data; ExternalInterface.call('webcam.flash_notify', "success", msg); } public function reset() { // reset video after taking snapshot if (bmp) { removeChild( bmp ); bmp = null; bmpdata = null; video.attachCamera(camera); addChild(video); } } } } \ No newline at end of file +package { /* JPEGCam v1.0.8 */ /* Webcam library for capturing JPEG images and submitting to a server */ /* Copyright (c) 2008 - 2009 Joseph Huckaby */ /* Licensed under the GNU Lesser Public License */ /* http://www.gnu.org/licenses/lgpl.html */ import flash.display.LoaderInfo; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.display.Bitmap; import flash.display.BitmapData; import flash.events.*; import flash.utils.*; import flash.media.Camera; import flash.media.Video; import flash.external.ExternalInterface; import flash.net.*; import flash.system.Security; import flash.system.SecurityPanel; import flash.media.Sound; import flash.media.SoundChannel; import flash.geom.Matrix; import com.adobe.images.JPGEncoder; import com.marstonstudio.UploadPostHelper; public class Webcam extends Sprite { private var video:Video; private var encoder:JPGEncoder; private var snd:Sound; private var channel:SoundChannel = new SoundChannel(); private var jpeg_quality:int; private var video_width:int; private var video_height:int; private var server_width:int; private var server_height:int; private var camera:Camera; private var bmp:Bitmap; private var bmpdata:BitmapData; private var url:String; private var form_data:Object; public function Webcam() { // class constructor flash.system.Security.allowDomain("*"); var flashvars:Object = LoaderInfo(this.root.loaderInfo).parameters; video_width = Math.floor( flashvars.width ); video_height = Math.floor( flashvars.height ); server_width = Math.floor( flashvars.server_width ); server_height = Math.floor( flashvars.server_height ); form_data = {}; stage.scaleMode = StageScaleMode.NO_SCALE; // stage.scaleMode = StageScaleMode.EXACT_FIT; stage.align = StageAlign.TOP_LEFT; stage.stageWidth = Math.max(video_width, server_width); stage.stageHeight = Math.max(video_height, server_height); // Hack to auto-select iSight camera on Mac (JPEGCam Issue #5, submitted by manuel.gonzalez.noriega) // From: http://www.squidder.com/2009/03/09/trick-auto-select-mac-isight-in-flash/ var cameraIdx:int = -1; for (var idx = 0, len = Camera.names.length; idx < len; idx++) { if (Camera.names[idx] == "USB Video Class Video") { cameraIdx = idx; idx = len; } } if (cameraIdx > -1) camera = Camera.getCamera( String(cameraIdx) ); else camera = Camera.getCamera(); if (camera != null) { camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler); video = new Video( Math.max(video_width, server_width), Math.max(video_height, server_height) ); video.attachCamera(camera); addChild(video); if ((video_width < server_width) && (video_height < server_height)) { video.scaleX = video_width / server_width; video.scaleY = video_height / server_height; } camera.setQuality(0, 100); camera.setKeyFrameInterval(10); camera.setMode( Math.max(video_width, server_width), Math.max(video_height, server_height), 30); // do not detect motion (may help reduce CPU usage) camera.setMotionLevel( 100 ); ExternalInterface.addCallback('_snap', snap); ExternalInterface.addCallback('_configure', configure); ExternalInterface.addCallback('_upload', upload); ExternalInterface.addCallback('_reset', reset); ExternalInterface.addCallback('_set_form_data', set_form_data); if (flashvars.shutter_enabled == 1) { snd = new Sound(); snd.load( new URLRequest( flashvars.shutter_url ) ); } jpeg_quality = 90; ExternalInterface.call('webcam.flash_notify', 'flashLoadComplete', true); } else { trace("You need a camera."); ExternalInterface.call('webcam.flash_notify', "error", "No camera was detected."); } } public function set_quality(new_quality:int) { // set JPEG image quality if (new_quality < 0) new_quality = 0; if (new_quality > 100) new_quality = 100; jpeg_quality = new_quality; } public function set_form_data(new_form_data:Object) { form_data = new_form_data; } public function configure(panel:String = SecurityPanel.CAMERA) { // show configure dialog inside flash movie Security.showSettings(panel); } private function activityHandler(event:ActivityEvent):void { trace("activityHandler: " + event); } public function snap(url, new_quality, shutter) { // take snapshot from camera, and upload if URL was provided if (new_quality) set_quality(new_quality); trace("in snap(), drawing to bitmap"); if (shutter) { channel = snd.play(); setTimeout( snap2, 10, url ); } else snap2(url); } public function snap2(url) { // take snapshot, convert to jpeg, submit to server bmpdata = new BitmapData( Math.max(video_width, server_width), Math.max(video_height, server_height) ); bmpdata.draw( video ); // draw snapshot on stage bmp = new Bitmap( bmpdata ); addChild( bmp ); // stop capturing video video.attachCamera( null ); removeChild( video ); // if URL was provided, upload now if (url) upload( url ); } public function upload(url) { if (bmpdata) { if ((video_width > server_width) && (video_height > server_height)) { // resize image downward before submitting var tmpdata = new BitmapData(server_width, server_height); var matrix = new Matrix(); matrix.scale( server_width / video_width, server_height / video_height ); tmpdata.draw( bmpdata, matrix, null, null, null, true ); // smoothing bmpdata = tmpdata; } // need resize trace("converting to jpeg"); var ba:ByteArray; encoder = new JPGEncoder( jpeg_quality ); ba = encoder.encode( bmpdata ); trace("jpeg length: " + ba.length); //URLRequest containing the form fields and the attached image var req : URLRequest = new URLRequest(url); req.method = URLRequestMethod.POST; req.data = UploadPostHelper.getPostData( 'dump.fm.webcam.test.jpg', ba, form_data ); req.requestHeaders.push(new URLRequestHeader('Cache-Control', 'no-cache') ); req.requestHeaders.push(new URLRequestHeader('Content-Type', 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary())); //URLLoader to load the request var loader : URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoaded); trace("sending post to: " + url); try { loader.load(req); } catch (error:Error) { trace("Unable to load requested document."); ExternalInterface.call('webcam.flash_notify', "error", "Unable to post data: " + error); } } else { ExternalInterface.call('webcam.flash_notify', "error", "Nothing to upload, must capture an image first."); } } public function onLoaded(evt:Event):void { // image upload complete var msg = "unknown"; if (evt && evt.target && evt.target.data) msg = evt.target.data; ExternalInterface.call('webcam.flash_notify', "success", msg); } public function reset() { // reset video after taking snapshot if (bmp) { removeChild( bmp ); bmp = null; bmpdata = null; video.attachCamera(camera); addChild(video); } } } } \ No newline at end of file diff --git a/webcam/com/marstonstudio/UploadPostHelper.as b/webcam/com/marstonstudio/UploadPostHelper.as index 857bc42..43eb429 100644 --- a/webcam/com/marstonstudio/UploadPostHelper.as +++ b/webcam/com/marstonstudio/UploadPostHelper.as @@ -36,7 +36,7 @@ package com.marstonstudio public static function getBoundary():String { if(_boundary.length == 0) { - for (var i:int = 0; i < 0x20; i++ ) { + for (var i:int = 0; i < 0x20; i++ ) { _boundary += String.fromCharCode( int( 97 + Math.random() * 25 ) ); } } @@ -66,7 +66,7 @@ package com.marstonstudio postData = BOUNDARY(postData); postData = LINEBREAK(postData); bytes = 'Content-Disposition: form-data; name="' + name + '"'; - for ( i = 0; i < bytes.length; i++ ) { + for ( i = 0; i < bytes.length; i++ ) { postData.writeByte( bytes.charCodeAt(i) ); } postData = LINEBREAK(postData); @@ -78,15 +78,15 @@ package com.marstonstudio //add Filedata to postData postData = BOUNDARY(postData); postData = LINEBREAK(postData); - bytes = 'Content-Disposition: form-data; name="Filedata"; filename="'; - for ( i = 0; i < bytes.length; i++ ) { + bytes = 'Content-Disposition: form-data; name="image"; filename="'; + for ( i = 0; i < bytes.length; i++ ) { postData.writeByte( bytes.charCodeAt(i) ); } postData.writeUTFBytes(fileName); postData = QUOTATIONMARK(postData); postData = LINEBREAK(postData); - bytes = 'Content-Type: application/octet-stream'; - for ( i = 0; i < bytes.length; i++ ) { + bytes = 'Content-Type: image/jpeg'; + for ( i = 0; i < bytes.length; i++ ) { postData.writeByte( bytes.charCodeAt(i) ); } postData = LINEBREAK(postData); @@ -94,21 +94,24 @@ package com.marstonstudio postData.writeBytes(byteArray, 0, byteArray.length); postData = LINEBREAK(postData); + // timb: i commented this shit out because i don't think it's needed //add upload filed to postData + /* postData = LINEBREAK(postData); postData = BOUNDARY(postData); postData = LINEBREAK(postData); bytes = 'Content-Disposition: form-data; name="Upload"'; - for ( i = 0; i < bytes.length; i++ ) { + for ( i = 0; i < bytes.length; i++ ) { postData.writeByte( bytes.charCodeAt(i) ); } postData = LINEBREAK(postData); postData = LINEBREAK(postData); bytes = 'Submit Query'; - for ( i = 0; i < bytes.length; i++ ) { + for ( i = 0; i < bytes.length; i++ ) { postData.writeByte( bytes.charCodeAt(i) ); } postData = LINEBREAK(postData); + */ //closing boundary postData = BOUNDARY(postData); @@ -124,7 +127,7 @@ package com.marstonstudio var l:int = UploadPostHelper.getBoundary().length; p = DOUBLEDASH(p); - for (var i:int = 0; i < l; i++ ) { + for (var i:int = 0; i < l; i++ ) { p.writeByte( _boundary.charCodeAt( i ) ); } return p; diff --git a/webcam/ru/inspirit/net/MultipartURLLoader.as b/webcam/ru/inspirit/net/MultipartURLLoader.as deleted file mode 100644 index bfd3db2..0000000 --- a/webcam/ru/inspirit/net/MultipartURLLoader.as +++ /dev/null @@ -1,582 +0,0 @@ -package ru.inspirit.net -{ - import flash.errors.IllegalOperationError; - import flash.events.Event; - import flash.events.EventDispatcher; - import flash.events.HTTPStatusEvent; - import flash.events.IOErrorEvent; - import flash.events.ProgressEvent; - import flash.events.SecurityErrorEvent; - import flash.net.URLLoader; - import flash.net.URLLoaderDataFormat; - import flash.net.URLRequest; - import flash.net.URLRequestHeader; - import flash.net.URLRequestMethod; - import flash.utils.ByteArray; - import flash.utils.Dictionary; - import flash.utils.Endian; - import flash.utils.setTimeout; - import flash.utils.clearInterval; - import ru.inspirit.net.events.MultipartURLLoaderEvent; - - /** - * Multipart URL Loader - * - * Original idea by Marston Development Studio - http://marstonstudio.com/?p=36 - * - * History - * 2009.01.15 version 1.0 - * Initial release - * - * 2009.01.19 version 1.1 - * Added options for MIME-types (default is application/octet-stream) - * - * 2009.01.20 version 1.2 - * Added clearVariables and clearFiles methods - * Small code refactoring - * Public methods documentaion - * - * 2009.02.09 version 1.2.1 - * Changed 'useWeakReference' to false (thanx to zlatko) - * It appears that on some servers setting 'useWeakReference' to true - * completely disables this event - * - * 2009.03.05 version 1.3 - * Added Async property. Now you can prepare data asynchronous before sending it. - * It will prevent flash player from freezing while constructing request data. - * You can specify the amount of bytes to write per iteration through BLOCK_SIZE static property. - * Added events for asynchronous method. - * Added dataFormat property for returned server data. - * Removed 'Cache-Control' from headers and added custom requestHeaders array property. - * Added getter for the URLLoader class used to send data. - * - * @author Eugene Zatepyakin - * @version 1.3 - * @link http://blog.inspirit.ru/ - */ - public class MultipartURLLoader extends EventDispatcher - { - public static var BLOCK_SIZE:uint = 64 * 1024; - - private var _loader:URLLoader; - private var _boundary:String; - private var _variableNames:Array; - private var _fileNames:Array; - private var _variables:Dictionary; - private var _files:Dictionary; - - private var _async:Boolean = false; - private var _path:String; - private var _data:ByteArray; - - private var _prepared:Boolean = false; - private var asyncWriteTimeoutId:Number; - private var asyncFilePointer:uint = 0; - private var totalFilesSize:uint = 0; - private var writtenBytes:uint = 0; - - public var requestHeaders:Array; - - public function MultipartURLLoader() - { - _fileNames = new Array(); - _files = new Dictionary(); - _variableNames = new Array(); - _variables = new Dictionary(); - _loader = new URLLoader(); - requestHeaders = new Array(); - } - - /** - * Start uploading data to specified path - * - * @param path The server script path - * @param async Set to true if you are uploading huge amount of data - */ - public function load(path:String, async:Boolean = false):void - { - if (path == null || path == '') throw new IllegalOperationError('You cant load without specifing PATH'); - - _path = path; - _async = async; - - if (_async) { - if(!_prepared){ - constructPostDataAsync(); - } else { - doSend(); - } - } else { - _data = constructPostData(); - doSend(); - } - } - - /** - * Start uploading data after async prepare - */ - public function startLoad():void - { - if ( _path == null || _path == '' || _async == false ) throw new IllegalOperationError('You can use this method only if loading asynchronous.'); - if ( !_prepared && _async ) throw new IllegalOperationError('You should prepare data before sending when using asynchronous.'); - - doSend(); - } - - /** - * Prepare data before sending (only if you use asynchronous) - */ - public function prepareData():void - { - constructPostDataAsync(); - } - - /** - * Stop loader action - */ - public function close():void - { - try { - _loader.close(); - } catch( e:Error ) { } - } - - /** - * Add string variable to loader - * If you have already added variable with the same name it will be overwritten - * - * @param name Variable name - * @param value Variable value - */ - public function addVariable(name:String, value:Object = ''):void - { - if (_variableNames.indexOf(name) == -1) { - _variableNames.push(name); - } - _variables[name] = value; - _prepared = false; - } - - /** - * Add file part to loader - * If you have already added file with the same fileName it will be overwritten - * - * @param fileContent File content encoded to ByteArray - * @param fileName Name of the file - * @param dataField Name of the field containg file data - * @param contentType MIME type of the uploading file - */ - public function addFile(fileContent:ByteArray, fileName:String, dataField:String = 'Filedata', contentType:String = 'application/octet-stream'):void - { - if (_fileNames.indexOf(fileName) == -1) { - _fileNames.push(fileName); - _files[fileName] = new FilePart(fileContent, fileName, dataField, contentType); - totalFilesSize += fileContent.length; - } else { - var f:FilePart = _files[fileName] as FilePart; - totalFilesSize -= f.fileContent.length; - f.fileContent = fileContent; - f.fileName = fileName; - f.dataField = dataField; - f.contentType = contentType; - totalFilesSize += fileContent.length; - } - - _prepared = false; - } - - /** - * Remove all variable parts - */ - public function clearVariables():void - { - _variableNames = new Array(); - _variables = new Dictionary(); - _prepared = false; - } - - /** - * Remove all file parts - */ - public function clearFiles():void - { - for each(var name:String in _fileNames) - { - (_files[name] as FilePart).dispose(); - } - _fileNames = new Array(); - _files = new Dictionary(); - totalFilesSize = 0; - _prepared = false; - } - - /** - * Dispose all class instance objects - */ - public function dispose(): void - { - clearInterval(asyncWriteTimeoutId); - removeListener(); - close(); - - _loader = null; - _boundary = null; - _variableNames = null; - _variables = null; - _fileNames = null; - _files = null; - requestHeaders = null; - _data = null; - } - - /** - * Generate random boundary - * @return Random boundary - */ - public function getBoundary():String - { - if (_boundary == null) { - _boundary = ''; - for (var i:int = 0; i < 0x20; i++ ) { - _boundary += String.fromCharCode( int( 97 + Math.random() * 25 ) ); - } - } - return _boundary; - } - - public function get ASYNC():Boolean - { - return _async; - } - - public function get PREPARED():Boolean - { - return _prepared; - } - - public function get dataFormat():String - { - return _loader.dataFormat; - } - - public function set dataFormat(format:String):void - { - if (format != URLLoaderDataFormat.BINARY && format != URLLoaderDataFormat.TEXT && format != URLLoaderDataFormat.VARIABLES) { - throw new IllegalOperationError('Illegal URLLoader Data Format'); - } - _loader.dataFormat = format; - } - - public function get loader():URLLoader - { - return _loader; - } - - private function doSend():void - { - var urlRequest:URLRequest = new URLRequest(); - urlRequest.url = _path; - urlRequest.contentType = 'multipart/form-data; boundary=' + getBoundary(); - urlRequest.method = URLRequestMethod.POST; - urlRequest.data = _data; - - if (requestHeaders.length && requestHeaders != null){ - urlRequest.requestHeaders = requestHeaders.concat(); - } - - addListener(); - - _loader.load(urlRequest); - } - - private function constructPostDataAsync():void - { - clearInterval(asyncWriteTimeoutId); - - _data = new ByteArray(); - _data.endian = Endian.BIG_ENDIAN; - - _data = constructVariablesPart(_data); - - asyncFilePointer = 0; - writtenBytes = 0; - _prepared = false; - if (_fileNames.length) { - nextAsyncLoop(); - } else { - _data = closeDataObject(_data); - _prepared = true; - dispatchEvent( new MultipartURLLoaderEvent(MultipartURLLoaderEvent.DATA_PREPARE_COMPLETE) ); - } - } - - private function constructPostData():ByteArray - { - var postData:ByteArray = new ByteArray(); - postData.endian = Endian.BIG_ENDIAN; - - postData = constructVariablesPart(postData); - postData = constructFilesPart(postData); - - postData = closeDataObject(postData); - - return postData; - } - - private function closeDataObject(postData:ByteArray):ByteArray - { - postData = BOUNDARY(postData); - postData = DOUBLEDASH(postData); - return postData; - } - - private function constructVariablesPart(postData:ByteArray):ByteArray - { - var i:uint; - var bytes:String; - - for each(var name:String in _variableNames) - { - postData = BOUNDARY(postData); - postData = LINEBREAK(postData); - bytes = 'Content-Disposition: form-data; name="' + name + '"'; - for ( i = 0; i < bytes.length; i++ ) { - postData.writeByte( bytes.charCodeAt(i) ); - } - postData = LINEBREAK(postData); - postData = LINEBREAK(postData); - postData.writeUTFBytes(_variables[name]); - postData = LINEBREAK(postData); - } - - return postData; - } - - private function constructFilesPart(postData:ByteArray):ByteArray - { - var i:uint; - var bytes:String; - - if(_fileNames.length){ - for each(var name:String in _fileNames) - { - postData = getFilePartHeader(postData, _files[name] as FilePart); - postData = getFilePartData(postData, _files[name] as FilePart); - postData = LINEBREAK(postData); - } - postData = closeFilePartsData(postData); - } - - return postData; - } - - private function closeFilePartsData(postData:ByteArray):ByteArray - { - var i:uint; - var bytes:String; - - postData = LINEBREAK(postData); - postData = BOUNDARY(postData); - postData = LINEBREAK(postData); - bytes = 'Content-Disposition: form-data; name="Upload"'; - for ( i = 0; i < bytes.length; i++ ) { - postData.writeByte( bytes.charCodeAt(i) ); - } - postData = LINEBREAK(postData); - postData = LINEBREAK(postData); - bytes = 'Submit Query'; - for ( i = 0; i < bytes.length; i++ ) { - postData.writeByte( bytes.charCodeAt(i) ); - } - postData = LINEBREAK(postData); - - return postData; - } - - private function getFilePartHeader(postData:ByteArray, part:FilePart):ByteArray - { - var i:uint; - var bytes:String; - - postData = BOUNDARY(postData); - postData = LINEBREAK(postData); - bytes = 'Content-Disposition: form-data; name="Filename"'; - for ( i = 0; i < bytes.length; i++ ) { - postData.writeByte( bytes.charCodeAt(i) ); - } - postData = LINEBREAK(postData); - postData = LINEBREAK(postData); - postData.writeUTFBytes(part.fileName); - postData = LINEBREAK(postData); - - postData = BOUNDARY(postData); - postData = LINEBREAK(postData); - bytes = 'Content-Disposition: form-data; name="' + part.dataField + '"; filename="'; - for ( i = 0; i < bytes.length; i++ ) { - postData.writeByte( bytes.charCodeAt(i) ); - } - postData.writeUTFBytes(part.fileName); - postData = QUOTATIONMARK(postData); - postData = LINEBREAK(postData); - bytes = 'Content-Type: ' + part.contentType; - for ( i = 0; i < bytes.length; i++ ) { - postData.writeByte( bytes.charCodeAt(i) ); - } - postData = LINEBREAK(postData); - postData = LINEBREAK(postData); - - return postData; - } - - private function getFilePartData(postData:ByteArray, part:FilePart):ByteArray - { - postData.writeBytes(part.fileContent, 0, part.fileContent.length); - - return postData; - } - - private function onProgress( event: ProgressEvent ): void - { - dispatchEvent( event ); - } - - private function onComplete( event: Event ): void - { - removeListener(); - dispatchEvent( event ); - } - - private function onIOError( event: IOErrorEvent ): void - { - removeListener(); - dispatchEvent( event ); - } - - private function onSecurityError( event: SecurityErrorEvent ): void - { - removeListener(); - dispatchEvent( event ); - } - - private function onHTTPStatus( event: HTTPStatusEvent ): void - { - dispatchEvent( event ); - } - - private function addListener(): void - { - _loader.addEventListener( Event.COMPLETE, onComplete, false, 0, false ); - _loader.addEventListener( ProgressEvent.PROGRESS, onProgress, false, 0, false ); - _loader.addEventListener( IOErrorEvent.IO_ERROR, onIOError, false, 0, false ); - _loader.addEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus, false, 0, false ); - _loader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError, false, 0, false ); - } - - private function removeListener(): void - { - _loader.removeEventListener( Event.COMPLETE, onComplete ); - _loader.removeEventListener( ProgressEvent.PROGRESS, onProgress ); - _loader.removeEventListener( IOErrorEvent.IO_ERROR, onIOError ); - _loader.removeEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus ); - _loader.removeEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError ); - } - - private function BOUNDARY(p:ByteArray):ByteArray - { - var l:int = getBoundary().length; - p = DOUBLEDASH(p); - for (var i:int = 0; i < l; i++ ) { - p.writeByte( _boundary.charCodeAt( i ) ); - } - return p; - } - - private function LINEBREAK(p:ByteArray):ByteArray - { - p.writeShort(0x0d0a); - return p; - } - - private function QUOTATIONMARK(p:ByteArray):ByteArray - { - p.writeByte(0x22); - return p; - } - - private function DOUBLEDASH(p:ByteArray):ByteArray - { - p.writeShort(0x2d2d); - return p; - } - - private function nextAsyncLoop():void - { - var fp:FilePart; - - if (asyncFilePointer < _fileNames.length) { - - fp = _files[_fileNames[asyncFilePointer]] as FilePart; - _data = getFilePartHeader(_data, fp); - - asyncWriteTimeoutId = setTimeout(writeChunkLoop, 10, _data, fp.fileContent, 0); - - asyncFilePointer ++; - } else { - _data = closeFilePartsData(_data); - _data = closeDataObject(_data); - - _prepared = true; - - dispatchEvent( new MultipartURLLoaderEvent(MultipartURLLoaderEvent.DATA_PREPARE_PROGRESS, totalFilesSize, totalFilesSize) ); - dispatchEvent( new MultipartURLLoaderEvent(MultipartURLLoaderEvent.DATA_PREPARE_COMPLETE) ); - } - } - - private function writeChunkLoop(dest:ByteArray, data:ByteArray, p:uint = 0):void - { - var len:uint = Math.min(BLOCK_SIZE, data.length - p); - dest.writeBytes(data, p, len); - - if (len < BLOCK_SIZE || p + len >= data.length) { - // Finished writing file bytearray - dest = LINEBREAK(dest); - nextAsyncLoop(); - return; - } - - p += len; - writtenBytes += len; - if ( writtenBytes % BLOCK_SIZE * 2 == 0 ) { - dispatchEvent( new MultipartURLLoaderEvent(MultipartURLLoaderEvent.DATA_PREPARE_PROGRESS, writtenBytes, totalFilesSize) ); - } - - asyncWriteTimeoutId = setTimeout(writeChunkLoop, 10, dest, data, p); - } - - } -} - -internal class FilePart -{ - - public var fileContent:flash.utils.ByteArray; - public var fileName:String; - public var dataField:String; - public var contentType:String; - - public function FilePart(fileContent:flash.utils.ByteArray, fileName:String, dataField:String = 'Filedata', contentType:String = 'application/octet-stream') - { - this.fileContent = fileContent; - this.fileName = fileName; - this.dataField = dataField; - this.contentType = contentType; - } - - public function dispose():void - { - fileContent = null; - fileName = null; - dataField = null; - contentType = null; - } -} \ No newline at end of file diff --git a/webcam/ru/inspirit/net/events/MultipartURLLoaderEvent.as b/webcam/ru/inspirit/net/events/MultipartURLLoaderEvent.as deleted file mode 100644 index 2b90855..0000000 --- a/webcam/ru/inspirit/net/events/MultipartURLLoaderEvent.as +++ /dev/null @@ -1,27 +0,0 @@ -package ru.inspirit.net.events -{ - import flash.events.Event; - - /** - * MultipartURLLoader Event for async data prepare tracking - * @author Eugene Zatepyakin - */ - public class MultipartURLLoaderEvent extends Event - { - public static const DATA_PREPARE_PROGRESS:String = 'dataPrepareProgress'; - public static const DATA_PREPARE_COMPLETE:String = 'dataPrepareComplete'; - - public var bytesWritten:uint = 0; - public var bytesTotal:uint = 0; - - public function MultipartURLLoaderEvent(type:String, w:uint = 0, t:uint = 0) - { - super(type); - - bytesTotal = t; - bytesWritten = w; - } - - } - -} \ No newline at end of file -- cgit v1.2.3-70-g09d2