Thursday, May 21st, 2009
Following my tutorial how to use PureMVC on Flashtuts+, I got a few comments about an error that Flash Debug Player throws when loading an image from Flickr:
SecurityError: Error #2122: Security sandbox violation: LoaderInfo.content: http://flashtuts.s3.amazonaws.com/ 026_PureMVC/App.swf cannot access http://farm3.static.flickr.com/2472/ 3549227972_7e6bd4d79a_t.jpg. A policy file is required, but the checkPolicyFile flag was not set when this media was loaded.
at flash.display::LoaderInfo/get content()
at com.flashtuts.view.component::ImagesView/handleLoaderComplete()
Now there are two ways around this:
- Using a PHP Proxy
This is the sneaky way as you’ll be loading images from Flickr and then putting them on your server. It’s not the best way, but it does have a great  advantage being that because the images are on your server, you won’t have to wait for the Flickr service (as it can get slow) nor will it effect the band width usage on your account.
- Using ‘LoaderContext‘ in AS3
This is the proper way as you’re not putting the images on your server, but there are times when Flickr does get busy and this often causes issues with your Flash file if you haven’t put in the proper ‘try’ and ‘catch’ statements.
So, let’s examine the two, starting with the PHPÂ approach:
Using a PHP Proxy
All we’re simply going to do is have a script that loads the image from Flickr and writes it to the local directory. Once that’s done, it will then serve this image back to us. If the image already exists, then there’s no need to load it again, so we’re caching them in a sense. Let’s look at the code:
So the first thing the script does is take the URL of the image we’re trying to load and hash it. This allows for simple naming of the file so that we can do easy conditional checks. It then checks to see if the image already exists and how long it’s been cached for. If it does exist and it’s less than an hour old (maybe an hour is too little, an image isn’t going to change that often so it’s worth making it more), it then skips the writing functions and serves it, otherwise it writes the image to the file system before serving it. Simples.
Using the proper method (with AS3)
As I mentioned, the way to do this with AS3 is to use LoaderContext. LoaderContext is a way of telling the Loader class to always check the policy file, and since, as it stands, the Loader class doesn’t seem to find the policy file, we enforce it using Security.loadPolicyFile(). So, using the code that I created in my tutorial on Flashtuts+, we simply need to add the LoaderContext() and Security.loadPolicyFile() commands:
public function init(images
:XML):void
{
var maxImages
:Number =
15;
var perRow
:Number =
5;
var xRowCount
:Number =
0;
var yRowCount
:Number =
0;
var loaderContext
:LoaderContext =
new LoaderContext( true );
var element
:XML;
var request
:URLRequest;
var loader:Loader;
for ( var i
:Number =
0; i
< maxImages
; i
++ )
{
element = images
..photo
[ i
];
request =
new URLRequest();
request
.url =
'http://farm' + element
.@farm
+ '.static.flickr.com/' + element
.@server
+ '/' + element
.@id
+ '_' +element
.@secret
+ '_t.jpg';
Security.loadPolicyFile( 'http://farm' + element
.@farm
+ '.static.flickr.com/crossdomain.xml' );
loader =
new Loader();
if ( xRowCount == perRow
)
{
xRowCount =
0;
yRowCount
++;
}
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, handleLoaderComplete
);
loader.alpha =
1;
loader.x = xRowCount
* 120;
loader.y = yRowCount
* 120;
loader.load( request
, loaderContext
);
xRowCount
++;
addChild( loader );
}
addBackButton
();
alpha =
0;
}
This is a snippet from the full 'ImagesView' class (which can be found on the tutorial's page) and all that I've added is the 'loaderContext' variable that creates a new instance of the LoaderContext class and states the the policy file should always be check, and then within the 'for' loop I've added a Security.loadPolicyFile statement to check each policy file for the different image farms that Flickr has. And I'm glad to say it works.
I've uploaded two files, the first one is the working one and the second is the one that still shows an error because these statements haven't been added to it.
So there we have it. If crossdomain policies are giving you issues, you either use a proxy (sneaky sneaky) or you load with a specified context.