October 7, 2008 1:57 PM
I cooked up a version of com.adobe.crypto.MD5 called MD5Stream that
accepts input data in chunks much like the way
java.security.MessageDigest works. The main application of this would
be when you need to pseudo-thread MD5 hashing of a large file or data
block using Actionscript 3.0 in an AIR or Flex application.
MD5Stream is based on code from the existing MD5 class in as3corelib and has been contributed to as3corelib. Here's the class description right from the source:
package com.adobe.crypto { /** * Perform MD5 hash of an input stream in chunks. This class 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. */ public class MD5Stream {
More examples on how to use this:
Usage 1:
var hash:MD5Stream = new MD5Stream(); /* in each call to update, input data is processed then and there. Only a small portion of it is saved for later so that the memory size doesn't grow to the total size of the input data */ hash.update(bytearr); /* call update when next chunk of data is available. */ hash.update(bytearr2); /* call complete to get the hash of all the data passed in */ strhash = hash.complete(bytearr3);
Usage 2:
var hash:MD5Stream = new MD5Stream(); hash.update(bytearr) strhash = hash.complete();
Usage 3 [same as com.adobe.crypto.MD5.hashBinary()
]:
var hash:MD5Stream = new MD5Stream(); strhash = hash.complete(bytearr);
I've tried out using the above class in an AIR application to hash
files greater than 100 MB using the openAsync() method of
flash.filesytem.FileStream
1. Simply call MD5Stream.update(data)2 when
the progress event fires and MD5Stream.complete() when the complete
event fires. The memory usage stayed fixed between 22 - 28 MB in my
test case.
MD5Stream is available in as3corelib.
[1] Make sure to set the
readAhead property of FileStream to something small like 16384 before doing
an openAsync. Otherwise, FileStream will try to read as far as
the end of the file making the async part irrelevant.
[2] data is a ByteArray into which fstream.bytesAvailable bytes
have been read in.