views:

579

answers:

4

Alright, currently I have my SWF hitting a php file that will go and find all the files I specify to it, add their sizes together and return their combined sizes as one number. I then use this number with a ProgressEvent listener to determine the current percentage of files downloading for that particular section of the website.

Pretty straightforward right? Well now using that PHP file is out of the question and I'm attempting to do everything inside the SWF instead of having it hit an outside script to get the numbers I need.

Is there any good way to get a file's size BEFORE I start loading it into flash? I really need the preloader to be a 0 to 100% preloader so I need the total number of bytes I will be downloading before it actually starts.

One thought I had was to just go through the array holding the file URLs, start loading them, getTotalBytes without displaying any loading, kill the load on the first tick, add up all those total bytes numbers, and then start the actual downloading process. This method seems very ugly and it will be a huge time waste as every time the user hits a pre loader on the site it will probably take a second or two to run through all the files, find their total and then actually start downloading.

Is there a better solution to this problem without going outside of flash to get the size of those files?

+2  A: 

You could do an HTTP HEAD request to the server for the files. This will return the header info (including file size) but not the actual file. You could then make a GET request to load the files.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

(Check out section 9.4 HEAD)

What I would probably do is a two tier progress bar (with 2 progress bars). One showing overall progress (0 to 100%) and one showing per file progress (as each file is downloaded).

That way, as long as you know the number of files to load, you can do the total progress without first having to hit the server to get the file sizes.

mike chambers

[email protected]

mikechambers
+1  A: 

Mike Chamber's idea will help you but it will still be slower than using something serverside, since you'll have to make a request for each file anyway. It's essentially the same of what you're saying yourself, but when you're explicitly asking for the headers it will be slightly faster. Use a Socket to do the request:

var socket : Socket = new Socket( );
socket.addEventListener( Event.CONNECT, connectHandler );
socket.addEventListener( ProgressEvent.SOCKET_DATA, dataHandler );
socket.connect( "yourserver.com", 80 );

function connectHandler( event : Event ) : void {
    var headers : String = "HEAD yourfilename.ext http/1.1\r\n";
    headers += "Host: yourserver.com\r\n";
    headers += "\r\n\r\n";
    socket.writeUTFBytes( headers );
    socket.flush( );
}

function dataHandler( event : ProgressEvent ) : void {
    trace( "Received headers\n" );
    trace( socket.readUTF( socket.bytesAvailable ) );
}
Antti
A: 

If it's absolutely necessary to control how the files are loaded, then I believe Mike Chambers' suggestion to make an HTTP HEAD request is the way to go.

However, unless there's a good reason not to, I'd simply begin loading all the files at once and get my file sizes from each file's getBytesTotal method. Since Flash gets its network stack from the browser, the number of files actually loaded concurrently will conform to the (user-definable) browser settings.

fenomas
A: 

The following is just for example purposes. In a real case I wouldnt use Timer, I would have an array or XML object to iterate through with a for loop, regardless it works great and basically once you hit the end of your loop (e.g. if(i == (length - 1)) have it call the functionality that starts the actual pre-loading now that we have our total. Now we iterate through the array or XML object again, but this time we do it only once each asset has loaded, not in a for loop. This asynchronous method can then sit there and compare how much data it has loaded and divide that by the earlier found total giving you your percentage.

var totalBytes:Number = 0;

var loader:Loader = new Loader();
var request:URLRequest = new URLRequest();
request.url = 'badfish.jpg';

var timer:Timer = new Timer(200);
timer.addEventListener(TimerEvent.TIMER, onTimer);

function onTimer(e:TimerEvent)
{
    loader.load(request);
    loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
}
function onProgress(e:ProgressEvent):void
{
    totalBytes+=e.bytesTotal;
    trace(e.bytesTotal,totalBytes);
    loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
}

timer.start();

<3AS3

Brian Hodge
Yea I had that idea as the last paragraph thought process from my question, instead of the timer though I'd just loop through all the files I needed and add them up similarly to what you suggested, luckily the server side script we had ended up working out, so I avoided having to do that.
vanhornRF