Flash AS3 read proxy server response with URLLoader - actionscript-3

I am running an embedded flash 'swf' inside a LAN network with a proxy server. Proxy server interrupts some urls and returns my usage information. I am trying to access this information by sending those urls. I can see this traffic in firebug ,But the URLLoader does not seem to read it. Neither Complete event or progress event get fired. I tried URLStream with a timer also,but availableBytes were always zero.Is it possible to read this information?
private var getLoader:URLLoader = new URLLoader();
private var sendRequest:URLRequest = new URLRequest();
public function XDomain() {
sendRequest= new URLRequest("requesturl");
getLoader.addEventListener(Event.COMPLETE, eventHandler);
getLoader.addEventListener(ProgressEvent.PROGRESS,eventHandler2);
getLoader.load(sendRequest);
}
private function eventHandler(event:Event):void {
trace("running");
}
private function eventHandler2(event:ProgressEvent):void {
trace("runninhg progresss");
}
Thanks in advance //
Edit: I had this security error
[SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]

"But the URLLoader does not seem to read it..."
Use URLStream (without a timer, cos what does that even achieve?) to reach the link and inside your related progressEvent use a readUTFBytes to get any text response data given by that link's server. Use progressEvent to also check size of any received bytes (the event fires multiple times, getting 64kb packets, until full data is downloaded).
about Error #2048:
URLloader is a decoder for visual data (jpg, png, swf, text) but for non-text data it expects a crossdomain.xml to exist at the other server you are accessing the swf from (both sides must also have a matching same http or https. Again best way to by-pass this is to just load the bytes into a byte array (via URLStream but the progressEvents now should write to your byte array) then later use URLLoader.loadBytes( yourSWFBytes );

Related

Why does URLStream complete event get dispatched when the file is not finished loading?

I'm writing an AIR kiosk app that every night connects to a WordPress server, gets a JSON file with paths to all the content, and then downloads that content and saves it to the kiosk hard drive.
There's several hundred files (jpg, png, f4v, xml) and most of them download/save with no problems. However, there are two f4v files that never get downloaded completely. The complete event does get dispatched, but if I compare the bytesTotal (from the progress event) vs bytesAvailable (from the complete event) they don't match up; bytesTotal is larger. The bytesTotal (from the progress event) matches the bytes on the server.
The bytesLoaded in the progress event never increases to the point that it matches the bytesTotal either so I can't rely on the progress event either. This seems to happen on the same two videos every time. The videos are not very large, one is 13MB and the other is 46MB. I have larger videos that download without any problems.
EDIT: After rebooting my computer, the two videos now finish downloading but I'm getting the same problem with a 300kb png file.
If I paste the url into Firefox it downloads correctly. I've also written a simple c# app to download the files and it is able to download them with no problems, so it appears to be a problem with Flash/AIR.
EDIT: here's a simpler version of the code, this is from a test project and it's 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?
}
}
}
Don't compare to bytesAvailable, use length instead. BytesAvailable is actually ByteArray.length - ByteArray.position. So if the position within the ByteArray has moved away from index 0, the bytesAvailable value will decrease. Length will always be the total number of bytes within the array.
Try comparing using length and see if this makes any difference. I don't have time to sift through your code to see if you are changing position at any point (either purposefully or accidentally; you can do it in more ways than one), so that's the best I can offer right now.
If anyone else has the same problem like I did. It turned out to be a caching problem which is present in AIR as well so a timestamp added to the request solves this: 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());
}
Your answer is in your question.
Normal URLs (files) - to this server this is a block of data. Once the server delivers the 'block of data' the delivery process is considered 'COMPLETE'. In this case if a file is 100kb, once the 100kb is received - Flash considers this as 'COMPLETE'.
URLStream - to the server this is [TWO] blocks of data (very simple way to look at it). The server will first serve the CONNECTION to the stream... then serve the STREAM DATA. This is handled in Flash just as its described.
Flash will consider the loading of the CONNECTION as 'COMPLETE', and NEVER check if the STREAM data is loaded - thats up to your server. In any streams you should actually check the [load progress] event and read each byte of data as it comes in... then construct as required.

URLLoader does not resond to .close()

My application requires that I am able to abort/close a URLLoader instance at any point in the post-connect stage; that is, regardless if I have connected and the file transfer has already begun, or whether I have connected, and the file transfer has yet to commence (the server has not begun sending the file yet).
Here is my code:
var myTextLoader:URLLoader = new URLLoader();
myTextLoader.load(new URLRequest("myText.txt"));
This is what I have noticed:
When I connect to a server, and the server starts sending the file immediately, DURING the actual file transfer, if I invoke myTextLoader.close(), it aborts immediately. This is expected. I can monitor this by executing the SWF in Firefox,and noticing that when I issue the close(), the network connecion goes from Pending to aborted.
However, if I connect to the server, and the file transfer has not actually begun yet (I have confirmed the connect event has fired, and the server has simply not begun sending the file), then myTextLoader.close() has no effect. Only AFTER the first bytes start being transferred from the server, will .close() have any effect. I can verify the connection is stuck in Pending in Firebug.. .close() has no effect until the transfer has started.
Any ideas how to work around this issue? I need to be able to invoke .close() and have the connection torn down regardless of the connection stage.
First thing I would think of, is create a bool "aborted" that is set to true where the close() method is invoked.
Like :
function abort():void {
_aborted = true;
myTextLoader.close();
}
Then check for its value anywhere in the onProgress event or any similar event, to actually call the URLLoader close() method again whenever its value is true...
function onProgress(evt:ProgressEvent):void {
if (_aborted) {
myTextLoader.close();
}
}
Its not a pretty thing and is an ugly workaround, but this could work, since when the first bits are actually received, you'll know if you already wanted to close it or not.
Did you find any bug report on that anywhere ?... I doubt it could be an intended behavior...
3rd party AS3 HTTPClient (https://github.com/gabriel/as3httpclient) appears to not exhibit this issue with close().

POST file upload using URLRequest

I have a quick question regarding POST file uploads in ActionScript 3. I am trying to upload a ByteArray from memory via POST to a server. I'm using the URLRequest class to send the data, and URLLoader because I want to monitor the progress. The relevant sections of code follows:
var uploadRequest:URLRequest = new URLRequest("http://127.0.0.1/upload.php");
uploadRequest.method = URLRequestMethod.POST;
uploadRequest.contentType = "multipart/form-data";
uploadRequest.data = myByteArray;
var uploader:URLLoader = new URLLoader;
uploader.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
uploader.addEventListener(Event.COMPLETE, onUploadComplete);
uploader.dataFormat = URLLoaderDataFormat.BINARY;
uploader.load(uploadRequest);
The problem is that I've set my callbacks to trace the upload progress, and the bytesTotal property of the ProgressEvent is always 1960 (the size of the request minus data?), even though the actual data is around 20MB and no file is uploaded even after the Complete event fires.
I've verified that upload.php functions correctly with a simple html form, and I can verify that myByteArray contains all of the data in question. Can anyone tell me what I'm doing wrong?
Edit:
I've attempted a couple of new things that I thought I should mention. The first is setting the content type to application/octet-stream instead of multipart/form-data, which had no effect other than increasing the number of bytes to 1964. I also checked the Apache error log and found the following text repeated a lot:
PHP Warning: Missing boundary in multipart/form-data POST data in Unknown on line 0
I'm guessing that Flash isn't formatting the HTTP request properly for whatever reason. Given that I created a FileReference that makes use of the same methods I set for the URLLoader to upload a file from disk, and got the expected result: the bytesTotal property matched the file size and the file was uploaded correctly.
Working from that I found a page in the Adobe developer docs that mentions uploading data to a server using FileReference.upload() by setting the data parameter of the URLRequest, so I tried the following code:
var uploadRequest:URLRequest = new URLRequest("http://127.0.0.1/upload.php");
uploadRequest.method = URLRequestMethod.POST;
uploadRequest.data = myByteArray;
fileRef = new FileReference;
fileRef.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
fileRef.addEventListener(Event.COMPLETE, onUploadComplete);
fileRef.upload(uploadRequest);
Which resulted in the following output:
ArgumentError: Error #2127: FileReference POST data cannot be type ByteArray.
I'm really stuck here. Any suggestions would be appreciated!
You should add more info to the "Content-Type" header:
uploadRequest.contentType = "multipart/form-data; boundary=<<boundary here>>";

Why Dispatching Event.OPEN Instead of IOErrorEvent.IO_ERROR?

Why does the load method of the URLStream class dispatch Event.OPEN instead of IOErrorEvent.IO_ERROR when the SWF is on a webserver and when trying to load an invalid URL?
The same doesn't apply when running the SWF locally.
Sample code:
var CLS_UrlStream:URLStream = new URLStream(); // Initialize URLStream class instance.
CLS_UrlStream.addEventListener(Event.OPEN, FUN_StreamHandler); // Listen for successful connections.
CLS_UrlStream.addEventListener(IOErrorEvent.IO_ERROR, FUN_StreamHandler); // Listen for conenction errors.
CLS_UrlStream.load(new URLRequest("InvalidURL")); // Load file.
private function FUN_StreamHandler(FUN_PAR_Event:Event):void {
trace("EVENT TYPE: " + FUN_PAR_Event.type);
}
// Outputs: EVENT TYPE: open
Event.OPEN gets triggered on load. So will always be called.
You probably want HTTPStatusEvent.HTTP_STATUS
When the SWF is running on the server and is requesting for a resource that doesn't exist, the server actually sends an error message which counts as data, thus there is no error event. The same didn't apply locally because there was no web server to respond with an error when a request for an nonexistent file is made. Discovered this by tracing live with the Monster Debugger.

unable to get HTTP response code/headers in actionscript 3?

I'm using URLLoader to POST to a server. The xml response from the server can respond with a 404 or a 403 (forbidden) error. However I am unable to get the response codes.
Here is the code
var urlString:String = "some url";
var urlRequest:URLRequest = new URLRequest(urlString);
var loader:URLLoader = new URLLoader();
loader.addEventListener( Event.COMPLETE, setXMLData );
loader.addEventListener( IOErrorEvent.IO_ERROR, ioHandler );
loader.addEventListener( HTTPStatusEvent.HTTP_STATUS, httpStatusHandler );
//...
public function httpStatusHandler(evt:HTTPStatusEvent):void {
trace("status is " + evt.status);
}
status is always 0 regardless whether i return 200, 400, 404, 301, 500, etc...
Any ideas?
For AIR Only you can use the httpResponseStatus. Otherwise in Flash/Flex without AIR you cannot.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/URLLoader.html#event:httpResponseStatus
httpResponseStatus Event
Event Object Type: flash.events.HTTPStatusEvent
HTTPStatusEvent.type property = flash.events.HTTPStatusEvent.HTTP_RESPONSE_STATUS
Language Version : ActionScript 3.0
Runtime Versions : AIR 1.0 AIR 1.0
Dispatched if a call to the load() method attempts to access data over HTTP, and Adobe AIR is able to detect and return the status code for the request.
Unlike the httpStatus event, the httpResponseStatus event is delivered before any response data. Also, the httpResponseStatus event includes values for the responseHeaders and responseURL properties (which are undefined for an httpStatus event. Note that the httpResponseStatus event (if any) will be sent before (and in addition to) any complete or error event.
the ability to look at the headers is limited in several browsers, therefore flash has a problem with being passed the information. this is mainly blamed on the browser settings, but i have yet to find one where it actually works. status event output.
i gave up and had the file print the response code in my projects, not wonderful (and somewhat defeating the point) but seems to work.
As a late answer (FWIW):
From what I've read, the status codes you get depend on what browser the Flash player is running in.
One article says you can only get 200 or 500. One SO question says they were getting 207 in Chrome but 0 in Firefox.
I, personally, have tested using the dev Flash player as well as an ActiveX version and was able to get many different 2XX/4XX HTTP status codes (but couldn't get the 3XX redirect codes I tried because the requests got redirected and returned 200s).