0

So my problem may be a little bigger than that, but I'm not certain. I'm creating a custom flash photo viewer for a client that dynamically loads the images with Loader objects. It takes a folder name in a specified directory on the server and calls a php page (using URLRequest) to get the workable contents of the folder. And then it loads it up from that array.

Here's the problem: it works FINE on my machine and every machine I've tested it on, but it DOESN'T work on my client's machine or some of his customer's machines. The loader bar that's at the bottom of the screen doesn't start to fill, which means that the images aren't starting to even load, and the status bar indicates that it continues to wait for a the server, yet never finishes waiting. This is consistent on a single machine, but varies across machines.

I've added diagnostics (a custom class I made to track certain vars and collect errors) to the thing to catch any errors, but it reports nothing on my client's machine. I've added flash version checking code, so the possibility of a lower version messing it up is gone...

I guess my question is, is there anything (security, environment, etc) that I could have overlooked that doesn't allow request objects or something to work on certain machines?? I've been ripping my hair out trying to figure this out!

My code (relevant sections):

    public static const LOADLIMIT:int = 4;

    public var paramObj:Object;
    private var imageRequests:Vector.<URLRequest>;
    private var loaderObj:Vector.<Loader>;
    private var nextToLoad:int = -1;

    //...

    public function Player(){
        //...
        paramObj = loaderInfo.parameters;
            if (!paramObj.root) paramObj.root = "http://site.com/images/";
            paramObj.imgloc = paramObj.imgloc;
            var res = bootstrapImages(paramObj.imgloc);
            if (res is String){
                loadErrorMsg.text = res;
                loadErrorMsg.visible = true;
                log.log(res);
            }
        //...
    }

    private function bootstrapImages(imgloc:String):*{
        try{
        if (!imgloc) return "No image location specified"; 

        var req:URLRequest = new URLRequest(paramObj.root+"getdirlist.php?name="+imgloc);
        var loader:URLLoader = new URLLoader();
        loader.addEventListener(Event.COMPLETE, directoryLoaded);
        loader.addEventListener(IOErrorEvent.IO_ERROR, function(ex:IOError){
            loadErrorMsg.text = "Error retreiving album data.";
            loadErrorMsg.visible = true;
            log.log(ex);
        });
        loader.load(req);
        } catch (ex:Error){
            log.log(ex); throw ex;
        }
    }

    private function directoryLoaded(e:Event){
        try{
        //directory will come down as a json array
        trace(e.target.data);
        try {
            var items:Array = JSON.decode(e.target.data);
        } catch (ex:Error){
            trace (ex.getStackTrace());
            loadErrorMsg.text = "Error parsing album data.";
            loadErrorMsg.visible = true;
            log.log(ex);
            return;
        } 

        if (items.length == 0){
            loadErrorMsg.text = "Invalid album name";
            loadErrorMsg.visible = true;
            log.log("Items length is 0.");
            return;
        }

        imageRequests = new Vector.<URLRequest>();
        loaderObj = new Vector.<Loader>();
        for each(var item:String in items){
            imageRequests.push(new URLRequest(paramObj.root+"coffeeimages/"+paramObj.imgloc+"/"+item));
            loaderObj.push(null);
        }

        //...show UI...

        for (var i:int = 0; i < LOADLIMIT; i++){
            imageLoaded(null);
        }
        } catch (ex:Error){
            log.log(ex); throw ex;
        }
    }

    private function imageLoaded(e:Event){
        try{
        //if this was called as a result of the load event, start the slideshow! :D
        if (e != null && e.target != null) {
            //stage.addChild((e.target as LoaderInfo).loader);
            trace(loaderObj[0]);
            if (loaderObj[0] != null && //if the first image is loaded
                loaderObj[0].contentLoaderInfo.bytesLoaded >= loaderObj[0].contentLoaderInfo.bytesTotal){ 
                trace(loaderObj[0].contentLoaderInfo.bytesLoaded, loaderObj[0].contentLoaderInfo.bytesTotal);
                loadErrorMsg.visible = false;
                playSlideshow(true);
            }
        }
        trace((e)?e.target:null, loaderObj);
        nextToLoad++;
        if (nextToLoad >= imageRequests.length) return;

        var r:URLRequest = imageRequests[nextToLoad];
        var l:Loader = new Loader();
        l.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
        l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(ex:ErrorEvent){
            loadErrorMsg.text = "Error parsing image data.";
            loadErrorMsg.visible = true;
            log.log(ex);
        });
        l.load(r);
        loaderObj[nextToLoad] = l;
        log.addObjectWatch(l);
        } catch (ex:Error){
            log.log(ex); throw ex;
        }
    }

Also, here's the player live on the site. Ctrl+Alt+Home brings up my diagnostics panel. Please tell me if it doesn't work for you as well, so I can be more worried about this... :/ Thanks.

Edit: I have added more debugging information. Turns out that on the computers that cannot load it, they are getting an HTTP status 0 returned when trying to bootstrap the album information. I have no idea what that means...

Tustin2121
  • 2,058
  • 2
  • 25
  • 38
  • Images are loading for me, FF4 Beta, Flash Player 10.1. And Chrome 5 and Safari 5, and IE8. – Aaron Aug 24 '10 at 04:34
  • Works for me as well FF 3.6.8 and IE 8(albeit a lot slow than FF for some reason) – Tommy Aug 24 '10 at 05:02
  • Works for me OSX Snow Leopard , Chrome 6.0.472.41 beta , FF 3.6.6 , Opera 10.53 , Safari 5.0.1 , Flash Player 10.1 debugger version – PatrickS Aug 24 '10 at 05:30
  • It may be useful to determine exactly which revision of the Flash Player and which specific web browser are causing this issue. Can you get that information from the people who are consistently able to reproduce the issue? – Aaron Aug 24 '10 at 20:20
  • Ugh.... no. Probably not. Generally my client's customers (and even my client himself to some extent) are the kind that don't know what to do with a computer besides surf the web. I can work it into the diagnostics, though (the Capabilities object looks promising in that respect). – Tustin2121 Aug 24 '10 at 20:38
  • Could be revealing, I discovered today when trying to solve a graphics display issue in Safari on only one person's system that the version of the Flash Player that shipped with CS5 was a beta prerelease of 10.1 that is, apparently, buggy. – Aaron Aug 24 '10 at 21:11
  • So my client tested the thing with the capabilities information. He has a newer version than I, and all the capabilities, I think, that my player does. So, that's not the solution.... tonight, I'm gonna try Tegeril's code (now that I finally have time). Thanks for your continued help, everyone. – Tustin2121 Aug 25 '10 at 13:39
  • Edit on the main post about the HTTP Status 0 Error... – Tustin2121 Sep 06 '10 at 20:58

3 Answers3

1

So, the problem was a matter of the URL its requesting...

My client was typing "www.site.com", while my code was requesting to "site.com". To Adobe, this is a cross site request, and NOT ALLOWED by default. One solution (and probably the easiest one) is to add a file called "crossdomain.xml" to the root folder of the website. Flash looks for this file when making a request. One example that worked for me is as follows:

//crossdomain.xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">

<cross-domain-policy>
    <allow-access-from domain="*.site.com" secure="false"/>
</cross-domain-policy>

Other solutions involve redirecting to one of the two ("site.com" redirects to "www.site.com"), or doing url rewriting, or getting url that they entered.

Tustin2121
  • 2,058
  • 2
  • 25
  • 38
0

I like the crossdomain.xml solution mentioned above, but we had a similar problem on our client PC's. The problem was that adblocker browser plugins were blocking the URLRequest of the actionscript. We are currently finding a solution to this.

Kevin Vella
  • 1,869
  • 1
  • 16
  • 18
0

A few things I noticed, you are only listening for Event.COMPLETE and IOErrorEvent.IO_ERROR. I'd suggest also listening for HTTPStatusEvent.HTTP_STATUS, Event.OPEN, though I haven't added those in, they may provide useful information if you still aren't getting anywhere.

You should not need a LoaderContext object if you are only loading images and not accessing their content, so that (security) really should not be a problem. You should definitely separate out your logic in imageLoaded so that it is not both the initiator and the completion handler for your Loaders.

Anyway, no clue if this will be of use to you, but I've made your code substantially more readable and reworked some things that made little sense.

public static const LOADLIMIT:int = 4;

private var paramObj:Object;
private var imageRequests:Vector.<URLRequest>;
private var loaderObj:Vector.<Loader>;
private var nextToLoad:int = -1;

public function Player(){
    paramObj = loaderInfo.parameters;

    //what is this all about, your backup URL is useless?
    if (!paramObj.root) {
        paramObj.root = "http://site.com/images/";
    }

    var res = bootstrapImages();
    if (res.length > 0){
        loadErrorMsg.text = res;
        loadErrorMsg.visible = true;
        //log.log kills me
        log.log(res);
    }
}

private function bootstrapImages():String {
    try {
        var req:URLRequest = new URLRequest(paramObj.root + "getdirlist.php?name=" + paramObj.imgloc);
        var loader:URLLoader = new URLLoader();
        loader.addEventListener(Event.COMPLETE, directoryLoaded);
        loader.addEventListener(IOErrorEvent.IO_ERROR, dataIOError);
        loader.load(req);
    } catch (ex:Error) {
        log.log(ex);
    }
    return "";
}

private function directoryLoaded(e:Event):void{
    trace(e.target.data);
    try {
        var items:Array = JSON.decode(e.target.data);
    } catch (ex:Error){
        trace (ex.getStackTrace());
        loadErrorMsg.text = "Error parsing album data.";
        loadErrorMsg.visible = true;
        log.log(ex);
        return;
    } 

    if (items.length == 0){
        loadErrorMsg.text = "Invalid album name";
        loadErrorMsg.visible = true;
        log.log("Items length is 0.");
        return;
    }

    imageRequests = new Vector.<URLRequest>();
    loaderObj = new Vector.<Loader>();
    for each(var item:String in items){
        imageRequests.push(new URLRequest(paramObj.root+"coffeeimages/"+paramObj.imgloc+"/"+item));
        loaderObj.push(new Loader());
    }

    for (var i:int = 0; i < LOADLIMIT; i++){
        loadNextImage();
    }
}

private function loadNextImage():void {
    nextToLoad++;
    if (nextToLoad < imageRequests.length) {
        loaderObj[nextToLoad].contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
        loaderObj[nextToLoad].contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, dataIOError);
        try {
            loaderObj[nextToLoad].load(imageRequests[nextToLoad]);
        }
        catch (e:Error) {
            log.log(ex);
        }
        log.addObjectWatch(loaderObj[nextToLoad]);
    }
}

private function dataIOError(e:IOError):void {
    loadErrorMsg.text = "IOError: " + e.errorID + " - " + e.name + ", " + e.message;
    loadErrorMsg.visible = true;
    log.log(ex);
}

private function imageLoaded(e:Event){
    //Start the slideshow if the first image has loaded
    loadNextImage();
    if (e.target == loaderObj[0]) {
        trace(loaderObj[0].contentLoaderInfo.bytesLoaded, loaderObj[0].contentLoaderInfo.bytesTotal);
        loadErrorMsg.visible = false;
        playSlideshow(true);
    }
}

Edit: You may simply wish to scrap your loading code entirely and instead use Bulk Loader

Aaron
  • 4,634
  • 1
  • 27
  • 43
  • Sorry, changed the backup url from the original, despite the fact that I supply a link to the site in my post. The backup url is the actual url in the actual code. Also, the log variable is my custom diagnostics object. :P – Tustin2121 Aug 24 '10 at 15:11
  • This one was good too: paramObj.imgloc = paramObj.imgloc; I just deleted it, hehe. There was a definite rework of your logic in my answer, though I can't say that it would necessarily fix your issue, it coherently separates loading and completion logic. I've seen an overly-aggressive garbage collector cause strange issues like you described... I was also curious about your pushing of nulls into the loaderObj Vector, so I changed that behavior. – Aaron Aug 24 '10 at 20:18
  • Ah, I didn't even realize I had that in there. That was from when there was a default value at the end of that assignment, until I decided not to use a default value. I'll try this out tonight to see if it changes anything. Thanks. :) – Tustin2121 Aug 24 '10 at 20:30