AS3 URLLoader throwing URL not found, but is connecting successfully - actionscript-3

Okay getting some weirdness. I have a simple URLLoader in AS3 that loads an external XML document. It's loading just fine, I get a correct 302 Not Modified response in Charles, however flash tells me:
"URL Not Found"
Here is the relevant code:
//=============================================================================================
public function openXML(name:String):void { //decides what XML data feed and opens it
//=============================================================================================
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();
//add event listener to URLLoader to call closeXML upon completion
xmlLoader.addEventListener(Event.COMPLETE, closeXML);
xmlLoader.load(new URLRequest("http://www.gessnerengineering.com/projects"));
//=========================================================
function closeXML(e:Event):void {
//=========================================================
xmlData = new XML(xmlLoader.data);
xmlLoader.removeEventListener(Event.COMPLETE, closeXML);
drawPage(name, xmlData);
}
}
The problem line according to the debugger is at:
xmlLoader.load(new URLRequest("http://www.gessnerengineering.com/projects"));
I've verified that I can browse to the URL via my browser and cURL, and Charles says that my SWF can and IS successfully accessing it too. However I still get this URL Not Found error. According to the Flash Actionscript 3 documentation, this is the absolute correct way to use URLLoader to load external data including XML.
Updated code with pastie.

I'm finding your code's structure a little odd - why do you have functions inside of a function?
I rewrote your code like this and it works perfectly fine (i just ran it on the timeline in flash cause i'm too lazy to set up a new project):
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();
var request:URLRequest = new URLRequest("http://www.gessnerengineering.com/projects");
request.method = URLRequestMethod.GET;
//=============================================================================================
function openXML(name:String):void { //decides what XML data feed and opens it
//=============================================================================================
//add event listener to URLLoader to call closeXML upon completion
xmlLoader.addEventListener(Event.COMPLETE, closeXML);
xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
xmlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
xmlLoader.load(new URLRequest("http://www.gessnerengineering.com/projects"));
}
function onIOError(e:IOErrorEvent):void {
trace("Error loading URL.");
}
function securityError(e:SecurityErrorEvent):void {
trace("security error");
}
function closeXML(e:Event):void {
trace('xmlLoader.data ' + xmlLoader.data);
xmlData = new XML(xmlLoader.data);
xmlLoader.removeEventListener(Event.COMPLETE, closeXML);
}
openXML('ljkl');

Without knowing all of the details, and assuming you implemented the RESTful services properly, your URLRequest might be calling the service with the wrong method (POST, rather than GET).
Check out this tutorial about calling RESTful services from Actionscript 3:
Consuming REST web Services in ActionScript 3
It has some good info on setting the request type and dealing with some of the other issues that can pop up (like setting the return data type, etc.).

Related

Can AS3 handle HTTP errors with Payloads?

I'd like to implement a RESTful API which returns HTTP error codes when needed. Can ActionScript 3 handle an HTTP error code (404, 500) response which contains a JSON message in its payload?
Are there any good references that I can use as feedback for our in-house Flash front-end team?
I've been struggling with this too. It seems that the answer is "no", AS3 cannot.
I have, intermittently, seen data come in through IOErrorEvent.currentTarget.data, but I am not able to consistently reproduce this.
You probably can do URLRequest and then handle the HTTP status
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest("XMLFile.xml");
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
private function httpStatusHandler(event:HTTPStatusEvent):void {
trace("httpStatusHandler: " + event);
}
loader.load(request);
check the complete example :
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequest.html
you can add dispatcher.addEventListener(Event.COMPLETE, completeHandler); to find out whats coming back.

Image path issue on as3

I'm trying to create a screensaver for one our of our display we have at work. Images will be uploaded to an external server, from that server I will have pull the images and xml file. so my flash app and my content will be in two different places. I'm getting an error "SecurityError: Error #2000: No active security context". how do I override error and get the images to my stage.
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML;
var imageList:XMLList;
var imageLoader:Loader = new Loader();
var timer:Timer =new Timer(5000);
var imageIndex:uint = 0;
var child:DisplayObject;
var path:String="http://bgxserv03.mgmmirage.org/interactivemedia/mmhub01/test/mb/edit_bay/hr/infoscreen/servamb/";
xmlLoader.load(new URLRequest(path +"output.xml"));
xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
timer.addEventListener(TimerEvent.TIMER, tick);
function xmlLoaded(e:Event) {
xmlData = new XML ( e.target.data);
imageList = xmlData.image.name;
timer.start();
loadImage(imageList[0]);
}
function imageLoaded(e:Event){
if (child){
myImageHolder.removeChild(child);
}
child = myImageHolder.addChild(imageLoader);
Tweener.addTween(child, {alpha:0, time:1, delay:4});
Tweener.addTween(child, {alpha:1, time:1, delay:5});
}
function loadImage(path:String){
imageLoader.load(new URLRequest( path +"photos/"));
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaded);
}
Any help would be deeply appreciate. Thank you.
You need to put the "Crossdomain.XML" on the server's root directory. This will allow your flash file to access the data (image in your case) from that server. You can get a sample xml from the following URL, customize it for your server:
Sample CrossDomain.XML
What you are missing is probably a crossdomain.xml policy file at the domain of your image/xml files.
Use this link to create a crossdomain.xml file and add it to the root of your image/xml domain like so : "http://bgxserv03.mgmmirage.org/crossdomain.xml"
The URLLoader load() function automatically checks for the crossdomain.xml. Loader class requires you specify that you are interested in checking for a policy file in a LoaderContext object sent to the load() function.
In your code, it looks like the error should be coming from the URLLoader xml file request, since it doesn't look like you are trying to access the bitmap data of your images in any way, which is normally what would throw a security error for image files. If it is a problem with the image loading part, then complete the following instructions and you should be set to go:
In your loadImage function, add a LoaderContext parameter to your load method call:
function loadImage(path:String){
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.checkPolicyFile = true;
imageLoader.load(new URLRequest( path +"photos/"), loaderContext);
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaded);
}
Check out the spec for more info on how to use the Loader class.
If you run into any trouble, this thread may be helpful.

loading images and video in AIR without HTTP

I'm curious what the correct methodology is for loading image and video data directly from the file system, without employing HTTP.
I'm writing an AIR slideshow application, and it works great but currently relies on a local MAMP server to hand the app all the media via the standard, tried and true, FLASH media loading methodologies.
I know that since FLASH was developed as a web plugin it handles this way of receiving data best, but I'd really like to extricate this rather onerous and unnecessary bit and have the app as a stand-alone player, however, I'm unclear what the "correct" way is to load the media.
I have the File objects ready and I've gotten as far as having the user select the local directory from which to pull the media and I'm getting a list of the files (based on their extensions) from the list... but now what?
You first have to put the content of your file in a ByteArray (code from FileStream documentation)
var bytes:ByteArray = new ByteArray();
var myFileStream:FileStream = new FileStream();
var myFile:File = File.documentsDirectory.resolvePath("test.jpg");
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, FileMode.READ);
function progressHandler(event:ProgressEvent):void
{
if (myFileStream.bytesAvailable)
{
myFileStream.readBytes(bytes, myFileStream.position, myFileStream.bytesAvailable);
}
else
{
myFileStream.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
loadImage();
}
}
Then you may load these bytes in a Loader to display the image (see method Loader.loadBytes)
function loadImage():void
{
var loader:Loader = new Loader();
loader.loadBytes(bytes);
addChild(loader);
}
Cheers
With this code the Loader fires the Event.COMPLTE event and you will be able to manipulate the Bitmap from it:
var bytes:ByteArray = new ByteArray();
var myFileStream:FileStream = new FileStream();
var myFile:File = File.documentsDirectory.resolvePath(YOUR_PATH);
myFileStream.addEventListener(Event.COMPLETE, fileCompleteHandler)
myFileStream.openAsync(myFile, FileMode.READ);
function fileCompleteHandler(event:Event):void
{
myFileStream.readBytes(bytes);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
loader.loadBytes(bytes);
function imageLoaded(e:Event):void
{
addChild(Bitmap(loader.content));
myFileStream.removeEventListener(Event.COMPLETE, fileCompleteHandler);
myFileStream.close();
}
}
PS: Thanks Kodiak, I made my code based on yours.

Trouble with DataEvent.UPLOAD_COMPLETE_DATA not firing

I am having some trouble with an AS3 script to upload data to the server via PHP and then return some values from the PHP upload script. I am using the FileReference.upload() function, and the files are being successfully uploaded, but the eventListener I attached to the DataEvent.UPLOAD_COMPLETE_DATA event is not triggering. Is there something I can do on the PHP end of things to manually trigger this event when the file is done uploading?
as3:
private function onFileLoaded(event:Event):void {
//var _fileReference:FileReference = event.target as FileReference;
//var data:ByteArray = fileReference["data"];
//var filename:String = fileReference.name;
var urlRequest:URLRequest = new URLRequest("http://www.arttoframes.com/canvasSystems/uploadImage.php");
urlRequest.method = URLRequestMethod.POST;
fileReference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onUploadComplete);
fileReference.upload(urlRequest);
}
private function onFileLoadError(event:Event):void {
fileReference.removeEventListener(Event.COMPLETE, onFileLoaded);
fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onFileLoadError);
}
private function onUploadComplete(event:Event):void {
trace("ok");
fileReference.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onUploadComplete);
var thumbReferenceName = fileReference.name.substr(0,fileReference.name.indexOf("."))+"_thumb"+fileReference.name.substr(fileReference.name.indexOf("."),4)+"?nocache=" + new Date().getTime()
var urlRequest:URLRequest = new URLRequest("http://www.arttoframes.com/canvasSystems/uploads/Thumbnails/"+thumbReferenceName);
var urlLoader:Loader = new Loader ();
urlLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onDownloadComplete);
//urlLoader.load(urlRequest);
}
So this is a long standing bug that Adobe claims they've fixed, but at least in Flex 3 lots of people claim they can reproduce it even after Adobe says they've fixed it. And that's including yours truly.
https://bugs.adobe.com/jira/browse/FP-1419
I'd employ a work around monitoring the progress directly and when all of it has uploaded manually dispatch the event or just do your work there. There are several work arounds you can try reading the comments in Jira.

Why is my URLLoader not dispatching when it completes?

I'm using a URLLoader to send a few key/value pairs to a php script, which then turns them into an e-mail, sends it (or not), and then echoes a string with a response.
At first it works fine. The URLLoader posts, and I get my e-mail a minute later, but for some reason I'm not getting my response back. In fact, my COMPLETE event doesn't seem to fire at all. This is confusing me because if I'm getting my e-mail, I know I must be sending everything properly. Here's my code:
public class Mailman{
public static const METHOD:String = URLRequestMethod.POST;
public static const ACTION:String = "mailer.php";
public static var myLoader:URLLoader = new URLLoader();
private static function onMessageProgress(e:Event){
var L:URLLoader = e.target as URLLoader;
Output.trace("PROGRESS: "+L.bytesLoaded+"/"+L.bytesTotal);
for(var k in L){
Output.trace(" "+k+": "+L[k]);
}
}
private static function onOpen(e:Event){
Output.trace("Connection opened");
}
private static function onComplete(e:Event){
Output.trace("Complete!");
}
private static function onStatusChange(e:HTTPStatusEvent){
Output.trace("Status Changed to "+e.status);
}
private static function onMessageFail(e:Event){
PanelManager.alert("ERROR: Could not send your request. Please try again later.");
}
public static function sendMessage(recipient:String,subject:String,message:String){
var _vars:URLVariables = new URLVariables();
_vars.recipient = recipient;
_vars.subject = subject;
_vars.message = message;
var req:URLRequest = new URLRequest(ACTION);
req.data = _vars;
req.method = METHOD;
myLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
myLoader.addEventListener(ProgressEvent.PROGRESS,onMessageProgress);
myLoader.addEventListener(Event.OPEN,onOpen);
myLoader.addEventListener(Event.COMPLETE,onComplete);
myLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS,onStatusChange);
myLoader.addEventListener(IOErrorEvent.IO_ERROR,onMessageFail);
myLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onMessageFail);
myLoader.load(req);
}
public static function test(){
sendMessage("john#example.com","test","this is a test message.");
}
function Mailman(){}
}
When I call Mailman.test(), I get my e-mail exactly like I expect, and this is what traces out:
Connection opened
PROGRESS: 45/45
Status Changed to 0
How can this be? If I'm understanding the documentation properly, the Open event happens when I begin downloading my response, and clearly that is happening, so how can I get back an http status of 0? Any ideas?
I found it.
The problem was with the URLLoader's dataFormat. This is the format for what you're getting BACK, not what you're sending. I switched it to URLLoaderDataFormat.TEXT and it worked perfectly.
Another reason this could happen - if you use weak references when registering your event listeners, and do not keep a reference to your URLLoader instance and the instance handling the event(s), GC may clean them up before they can receive any events.
//make sure the URLLoader and onComplete instances are not local vars
var req:URLRequest = new URLRequest("dosomething.php");
myLoader.addEventListener(Event.COMPLETE, onComplete, false, 0, TRUE);
myLoader.load(req);
Ok I found the answer in my case it was .NET page which was responsible for Status=0 in Chrome. What we were doing that in .net page at the line after writing response to be sent back to flash, we were closing the response object which was reseting the page and because of which Chrome was showing status=0 and couldn't render the result. After commenting out the response.close line it started working fine.
I wrote my experience with this problem and how i was able to solve it at http://viveklakhanpal.wordpress.com/2010/07/01/error-2032ioerror/
Thanks,
Vivek.