as3corelib Tutorial:How to Use MD5Stream Class in Flex

golf-128x128 This class performs MD5 hash of an input stream in chunks. It is based on com.adobe.crypto.MD5 and can process data in chunks. Both block creation and hash computation are done together for whatever input is available so that the memory overhead at a time is always fixed. Memory usage is governed by two parameters: one is the amount of data passed in to update() and the other is memoryBlockSize. The latter comes into play only when the memory window exceeds the pre allocated memory window of flash player. Usage: create an instance, call update(data) repeatedly for all chunks and finally complete() which will return the md5 hash..

Search-256x256 Demo | DownloadDownload Full Project

This demo loads images into flash player with the new load() and save() features of FileReference provided by flash player 10, compute and compare hash strings of each image in order to find the duplicated images.

Properties:

1. memoryBlockSize

public var memoryBlockSize:int = 16384

Change this value from the default (16384) in the range of MBs to actually affect GC as GC allocates in pools of memory

Methods:

1. complete()

public function complete(input:ByteArray = null):String

Pass in chunks of the input data with update(), call complete() with an optional chunk which will return the final hash. Equivalent to the way java.security.MessageDigest works.

Parameters:

input:ByteArray (default = null) — The optional bytearray chunk which is the final part of the input

Returns:

String — A string containing the hash value

2. resetFields()

public function resetFields():void

Re-initialize this instance for use to perform hashing on another input stream. This is called automatically by complete().

3. update()

public function update(input:ByteArray):void

Pass in chunks of the input data with update(), call complete() with an optional chunk which will return the final hash. Equivalent to the way java.security.MessageDigest works.

Parameters:

input:ByteArray — The bytearray chunk to perform the hash on

Screenshot:

MD5Stream-01

Click “browser” to select images to be loaded and compared.

MD5Stream-02

Click “load” to load selected images and click the file name to display the related image.

MD5Stream-03

Click “check” to compute hash strings for each image file and compare them to determine the duplicated ones.

The following is full source code of MD5StreamDemo.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute" xmlns:net="flash.net.*"
	creationComplete="initApp();">
	<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.controls.Image;
			import mx.core.UIComponent;
			import mx.graphics.codec.JPEGEncoder;
			import mx.events.ListEvent;
			import mx.utils.ObjectProxy;
			import com.adobe.crypto.MD5Stream;

			private var frl:FileReferenceList; 

			[Bindable]
			private var selectedFilesDataProvider:Array;

			[Bindable]
			private var loadCount:int = 0;

			private function initApp():void
			{
				frl = new FileReferenceList();
				selectedFilesDataProvider = new Array();

				frl.addEventListener(Event.SELECT,filesSelectHandler);

				image = new Image();
				imageContainer.addChild(image);
			}		

			private function browser():void
			{
				panel.status = "browse";

				frl.browse([new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png")]);
			}

			private function filesSelectHandler(event:Event):void
			{
				panel.status = "selected";

				selectedFilesDataProvider = new Array();

				loadCount = 0;

				image.graphics.clear();
				image.width = 0;
				image.height = 0;

				var frObj:ObjectProxy;

				for each(var fr:FileReference in frl.fileList)
				{
					frObj = new ObjectProxy();
					frObj.name = fr.name;
					frObj.target = fr;
					frObj.duplicated = null;

					selectedFilesDataProvider.push(frObj);

					fr.addEventListener(Event.COMPLETE,fileLoadCompleteHandler);
				}
			}

			private function load():void
			{
				panel.status = "loading";

				for each(var fr:FileReference in frl.fileList)
				{
					fr.load();
				}
			}

			private function fileLoadCompleteHandler(event:Event):void
			{
				loadCount++;
				if(loadCount == selectedFilesDataProvider.length)
				{
					panel.status = "load complete";
				}
			}

			private var image:Image;

			private function showImage(event:ListEvent):void
			{
				var data:Object = event.itemRenderer.data.target.data;

				if(data != null)
				{
					var loader:Loader = new Loader();
					loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
					loader.loadBytes(ByteArray(data));
				}
				else
				{
					Alert.show("you should load all the images first");
				}
			}

			private function completeHandler(event:Event):void
			{

				var bitmap:Bitmap = Bitmap(event.currentTarget.loader.content);
				var bitmapData:BitmapData = bitmap.bitmapData;

				image.width = bitmapData.width;
	            image.height = bitmapData.height;

	         	image.graphics.clear();
	            image.graphics.beginBitmapFill(bitmapData);
	            image.graphics.drawRect(0,0,bitmapData.width,bitmapData.height);
	            image.graphics.endFill();
			}

			private function checkDuplicate():void
			{
				panel.status = "checking";
				callLater(doCheck);
			}

			private function doCheck():void
			{
				var encrypted:String = "";
				var md5Stream:MD5Stream = new MD5Stream();
				var md5Keys:Object = new Object();

				for(var i:int = 0 ; i < selectedFilesDataProvider.length; i++)
				{
					var frObj:ObjectProxy = ObjectProxy(selectedFilesDataProvider[i]); 

					var byteArray:ByteArray = ByteArray(frObj.target.data);

					var byteArray1:ByteArray = new ByteArray();
					var byteArray2:ByteArray = new ByteArray();
					var byteArray3:ByteArray = new ByteArray();

					var position:int = byteArray.length / 3;
					byteArray.readBytes(byteArray1,0,position);
					byteArray.readBytes(byteArray2,0,position);
					byteArray.readBytes(byteArray3,0);

					md5Stream.update(byteArray1);
					md5Stream.update(byteArray2);
					md5Stream.update(byteArray3);

					encrypted = md5Stream.complete();

					// The codes above from line "var byteArray:ByteArray = ByteArray(frObj.target.data);"
					// are equal to "encrypted = md5Stream.complete(byteArray);", it just a demo to show
					// we are able to compute data , like stream, in chunks.

					if(md5Keys.hasOwnProperty(encrypted))
					{
						frObj.duplicated = true;
						frObj.name = frObj.name + "(" + md5Keys[encrypted].name + ")";
					}
					else
					{
						md5Keys[encrypted] = frObj;
						md5Keys[encrypted].duplicated = false;
					}
				}

				panel.status = "checked";
			}
		]]>
	</mx:Script>
	<mx:Panel id="panel"
		title="MD5Stream Demo"
		width="100%" height="100%" layout="absolute">
		<mx:HDividedBox width="100%" height="100%">
			<mx:List id="selectedFiles"
				height="100%"
				width="100%"
				itemClick="showImage(event);"
				dataProvider="{selectedFilesDataProvider}">
				<mx:itemRenderer>
					<mx:Component>
						<mx:HBox>
							<mx:Label text="{data.name}" color="{data.duplicated == null?0x000000:(!data.duplicated)?0x0099ff:0xff0000}"/>
							<mx:Label text="{data.duplicated == null?'unchecked':(!data.duplicated)?'ready':'duplicated'}"/>
						</mx:HBox>
					</mx:Component>
				</mx:itemRenderer>
			</mx:List>
			<mx:Canvas id="imageContainer" width="100%" height="100%">

			</mx:Canvas>
		</mx:HDividedBox>
		<mx:ControlBar>
			<mx:Button label="browser" click="browser();"/>
			<mx:Button label="load" click="load();"/>
			<mx:Button label="check" enabled="{loadCount == selectedFilesDataProvider.length &amp;&amp; selectedFilesDataProvider.length!= 0}" click="checkDuplicate();"/>
		</mx:ControlBar>
	</mx:Panel>
</mx:Application>

Enjoy!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Reddit
  • Technorati
  • StumbleUpon
  • Twitter
RSS Enjoy this Post? Subscribe to Ntt.cc

RSS Feed   RSS Feed     Email Feed  Email Feed Follow us Follow us
You can leave a response, or trackback from your own site.

One Response to “as3corelib Tutorial:How to Use MD5Stream Class in Flex”

  1. kg says:

    This is great! Did you have to do anything special to get Flex Builder to target the v10 classes? Mine won’t recognize FileReference.load()

Leave a Reply