搜尋部落格文章

2013年2月5日 星期二

[轉] 圖片安全性操作解決方法

AS3 - Load a Remote Image from Any URL / Domain with No Stupid Security Sandbox Errors

Friday, September 18, 2009 by Sean P

Issue:

You want to load an image from an unkown external URL. It works on your computer... Sandbox Security error online (and/or the annoying images just showing up as solid white feature).
By default, Flash wants a crossdomain.xml file on the server you are loading from, but let's say there is none, because it's probably not your website.  Well, then the flash player isn't going to let you take that data and do what you want with it.
Attempting to do so will give you some error similar to:
*** Security Sandbox Violation ***
SecurityDomain 'http://www.designercolin.com/temp/ispire/get_boards.php' tried to access incompatible context 'somewebsite.com/someImage_here.jpg'

Half-Solution (aka the adobe way):

According to adobe's docs you need to do a couple things to work around this (to not access this remote data directly)- bypass policy file, and don't manipulate it in any way (ahem-lame).  See the next solution if you need to access or smooth the bitmap data.
1)  Use a LoaderContext instance with checkPolicyFile=false - this will tell it not to worry about the cross-domain issue and use the loader context object as 2nd parameter in Loader.load() call
var lc:LoaderContext = new LoaderContext();
lc.checkPolicyFile = false; // bypass security sandbox / policy file - does this effect quality when scaling? 

_myLoader = new Loader();
_myLoader.contentLoaderInfo.addEventListener(Event.INIT, onImageLoaded);

// load new url
_myURLRequest = new URLRequest($url);
_myLoader.load(_myURLRequest, lc);

2) Show the loaded image - This is where you may get the error (this is what had me pulling my hair out) 
Even with the checkPolicyFile = false set, I had to add the loader to a SPRITE (not movieclip, and not the loader content!), as this would be accessing data outside the sandbox
private function onImageLoaded($e:Event):void
{
  _innerImage = this.addChild(new Sprite());
  //_innerImage.addChild($e.currentTarget.content); // doesn't work. sandbox security error 
  _innerImage.addChild(_myLoader);
}
...by doing this, you will not have accessed this image data in any way to get the error, so you can load the image data but if you need to access the bitmapdata directly (or create a movie clip apparently?), I don't think it will work.
I'm not sure exactly why adding to a Sprite() instead of MovieClip() allowed it to work for me, they both are DisplayObjects, maybe there is something in the MovieClip constructor that accesses the image data... Whatever, it's stupid that you have to do that in the first place, so why would the method make sense!  See the other / better solution below..

Quality Question- for remote image data without policy file:

What I really want to know is (for printing purposes) - using this method, since there is no access directly to the image data, when you scale the image... does it not render with smoothing / anti-aliasing?  Is it poor quality outside of native dimensions?  Or is it basically the same quality as scaling a local image within security domain?  Final conclusion is that it's better to use a proxy if the image has to be anything but native (original size/scale)...

Better Solution- Go Around It

Well, since flash is finicky and now has had different bugs with different flash player versions, the smart thing to do is cut your losses and just go around this issue.  A local .php file or similar service as a proxy to cross-domains URLs will do the trick and retrieve the images and flash will basically think they were hosted locally.
Then, in flash you should set up a class that will prefix URLs for you, maybe extend the URLLoader...
However you do it, you want to prefix remote URLs with your proxy URL, and pass along the intended URL something like:
http://www.YourFlashSite.com/proxy/getimage.php?url=http://someOtherWebsite.com/someImage.jpg
On creating the PHP proxy to retrieve the file.. theres a few you can find with google but i have had issues with the majority of them-
One common proxy issue with Flash is that if your progressEvent.bytesTotal is 0 (making your preloader show Infinity) it may be because your server has gzip enabled.  You can use an app like Charles to see what your http activity looks like and see if there is gzip compression on the responses... turn off gzip for your proxy file and you're golden.