Why is the URLStream event completion dispatched when the file is not loading?
I am writing an AIR kiosk application that connects to a WordPress server every night, receives a JSON file with paths to all content, and then downloads that content and stores it on the kiosk's hard drive.
There are several hundred files (jpg, png, f4v, xml) and most of them can be loaded / saved without problems. However, there are two f4v files that are never fully loaded. The full event is dispatched, but if I compare bytesTotal (from the progress event) vs bytesAvailable (from the full event) they are not the same; bytesTotal more. BytesTotal (from progress event) matches bytes on the server.
The bytes loaded in the progress event never grow to the point where it matches the Total byte, so I can't rely on the progress event either. It seems to be happening in the same two videos every time. The videos are not very big, one is 13MB and the other is 46MB. I have larger videos that load without issue.
EDIT: After restarting my computer, the two videos finish downloading, but I get the same problem with a 300KB PNG file.
If I paste the url into Firefox it loads correctly. I also wrote a simple C # application to download files and it can download them without issue, so this is a Flash / AIR issue.
EDIT: Here's a simpler version of the code, this is from a test project and this is the only code (the url is on our local network, so you won't be able to download the file yourself):
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.URLRequest;
import flash.net.URLStream;
[SWF(backgroundColor="#000000", frameRate="24", width="640", height="480")]
public class Test extends Sprite {
private var fileSize:Number;
private var stream : URLStream;
private var url:String = "http://192.168.150.219/wordpress2/wp-content/uploads/2012/12/John-Butler-clip1.f4v";
public function Test() {
if (stage)
init();
else
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void {
this.removeEventListener(Event.ADDED_TO_STAGE, init);
stream = new URLStream();
stream.addEventListener(ProgressEvent.PROGRESS, onLoadProgress);
stream.addEventListener(Event.COMPLETE, onLoadComplete);
stream.load(new URLRequest(url));
}
private function onLoadProgress(event:ProgressEvent):void {
fileSize = event.bytesTotal;
var percent:Number = event.bytesLoaded / event.bytesTotal * 100;
trace(percent + "%"); // this never gets to 100%
}
private function onLoadComplete(event:Event):void {
trace("loaded", stream.bytesAvailable, "of", fileSize);
// outputs "loaded 13182905 of 13184365"
// so why is it "complete" when it isn't fully downloaded?
}
}
}
source to share
Don't compare with bytesAvailable
, use instead length
. BytesAvailable actually ByteArray.length - ByteArray.position
. Therefore, if the position in the ByteArray has moved away from index 0, the bytesAvailable value will decrease. The length will always be the total number of bytes in the array.
Try to compare the length and see if it doesn't matter. I donβt have time to sift through your code to see if you change position at any time (on purpose or accidentally, you can do more than one), so this is the best I can suggest right now.
source to share
If anyone else has the same problem as me. This turned out to be a caching issue that is present in AIR, so adding a timestamp to the request solves the following: http://www.newtonflash.com/blog/as3/prevent-xml-caching-problem/#comment-43
{
var xmlPath:String="replaceYourXMLPathHere.xml"
var urlReq:URLRequest = new URLRequest(xmlPath+"?time=" + new Date().getTime());
}
source to share
Your answer is in your question.
Regular URLs (files) - this is a block of data to this server. After the server delivers a "block of data", the delivery process is considered " FULL ". In this case, if the file is 100kb, after receiving 100kb - Flash considers it " COMPLETE ".
URLStream is [ TWO strong>] chunks on the server (a very easy way to look at it). The server will first serve the CONNECTION to the stream ... then open the STREAM DATA . This is done in Flash in the same way as described.
Flash will treat CONNECTION loading as COMPLETE and NEVER check that STREAM data is loaded - it's up to your server. In any streams, you should actually check for the [load progress] event and read each byte of data as it occurs ... then build as needed.
source to share