I'm looking at a tutorial to display placemarks using a KML file on a flex application. I'm using IGN API (openscales) in flex project.
The example works perfectly (http://openscales.org/userguide/examples/srcview/source/KMLExample.mxml.
<os:KML url="http://www.parisavelo.net/velib.kml"
proxy="http://openscales.org/proxy.php?url="
numZoomLevels="20"
style="{Style.getDefaultCircleStyle()}"/>
But when I'm hosting the same kml file on my server like that :
<os:KML url="http://www.cycom.org/velib.kml"
proxy="http://openscales.org/proxy.php?url="
numZoomLevels="20"
style="{Style.getDefaultCircleStyle()}"/>
Placemarks don't show up on the map. I tried to host the kml file on different hosts but that doesn't change. Do you have a clue ?
Thank you.
You need to add a crossdomain.xml to the server side (in root folder) to allow the application to access your KML file. For example, if you want to allow access to your server to all IPs and domain names just use a simple wild card as below in your crossdomain.xml file:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
For more information about using crossdomain file see: Transfering Data Accross Domains Using crossdomain.xml
If you don't have access to the server or if this solution doesn't work for you, you have to modify the KML.as class in openscales (found in org.openscales.core.layer package).
Change line 19
private var _request: XMLRequest = null;
to
private var _request :URLLoader = null;
Here is the entire modified KML class:
package org.openscales.core.layer
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import org.openscales.core.Trace;
import org.openscales.core.feature.Feature;
import org.openscales.core.format.KMLFormat;
import org.openscales.core.request.XMLRequest;
import org.openscales.geometry.basetypes.Bounds;
public class KML extends FeatureLayer
{
private var _url :String = "";
private var _request :URLLoader = null;
private var _kmlFormat :KMLFormat = null;
private var _xml :XML = null;
public function KML ( name :String,
url :String,
bounds :Bounds = null )
{
this._url = url;
this.maxExtent = bounds;
super( name );
this._kmlFormat = new KMLFormat();
}
override public function destroy () :void
{
if ( this._request )
this._request = null;
this.loading = false;
super.destroy();
}
override public function redraw ( fullRedraw :Boolean = true ) :void
{
if ( !displayed )
{
this.clear();
return;
}
if ( !this._request )
{
this.loading = true;
this._request = new URLLoader();
this._request.addEventListener( Event.COMPLETE, onSuccess );
this._request.addEventListener( IOErrorEvent.IO_ERROR, onFailure );
this._request.load( new URLRequest( url ));
}
else
{
this.clear();
this.draw();
}
}
public function onSuccess ( event :Event ) :void
{
this.loading = false;
var loader :URLLoader = event.target as URLLoader;
// To avoid errors if the server is dead
try
{
this._xml = new XML( loader.data );
if ( this.map.baseLayer.projection != null && this.projection != null && this.projection.srsCode != this.map.baseLayer.projection.srsCode )
{
this._kmlFormat.externalProj = this.projection;
this._kmlFormat.internalProj = this.map.baseLayer.projection;
}
this._kmlFormat.proxy = this.proxy;
var features :Vector.<Feature> = this._kmlFormat.read( this._xml ) as Vector.<Feature>;
this.addFeatures( features );
this.clear();
this.draw();
}
catch ( error :Error )
{
Trace.error( error.message );
}
}
protected function onFailure ( event :Event ) :void
{
this.loading = false;
Trace.error( "Error when loading kml " + this._url );
}
public function get url () :String
{
return this._url;
}
public function set url ( value :String ) :void
{
this._url = value;
}
override public function getURL ( bounds :Bounds ) :String
{
return this._url;
}
}
}
Related
I have a web application developed using flex and cakephp. My client need to make a desktop application of that web application using Adobe Air. The conversion of the flex to Air is done successfully. I the flex application the communication of flex and cakephp is handled using a remotes controller.
In air application I have a problem of authenticating the user with cakephp default user authentication. Can anyone help me to find a solution for this?
i suggest you to send your user credentials via POST to your cakephp backend.
A login function in your UsersController would look something like this:
public function login() {
if ($this->Auth->login()) {
$this->serviceResponse(Status::SUCCESS);
} else {
$this->serviceResponse(Status::AUTH_FAILED);
}
}
// this is just an example out of my appcontroller to send json responses
public function serviceResponse($code, $data = array()) {
$response = compact('code', 'data');
$this->response->body(json_encode($response));
$this->response->send();
$this->shutdownProcess();
exit;
}
// I also defined a class for return statuses
class Status {
const SUCCESS = 'success';
const ERROR = 'error';
...
}
Basically, you want to send the validation request as an ajax request. To do that you need to modify headers, capture session ids through cookies and post them to keep the session alive. It expects a JSON object returned from Cake.
I've created a couple Flex classes that achieve just this for a Flex Mobile App and a CakePHP backend. It should work the same for your needs.
It's in two files, the AutoValidationUrlRequest.as extends the HeaderURLRequest.as file. I'm not positive but there may be a couple variables to change, but overall it works very well and probably won't take more than a couple changes to get it working on your app.
To use it, simply create a new AutoValidationUrlRequest object and add an event listener on the headerUrlRequestComplete Event and then run AutoValidationUrlRequest.send(...) to POST. there is also a handy method called convertToPostVars for easy Cake Friendly Post variables.
AutoValidationUrlRequest.as:
package libs
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import models.LocalDeviceData;
import models.Model;
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.utils.ObjectUtil;
[Event("LoginFailed")]
[Event("MobileUserDoesNotExist")]
public class AutoValidationURLRequest extends HeaderURLRequest
{
public static const LOGIN_FAILED:String = "LoginFailed";
public static const MOBILE_USER_DOES_NOT_EXIST:String = "MobileUserDoesNotExist";
/**
* will automatically be set by this class, if not set will login
*/
public var requestHeaders:Object = new Object();
private var _cookie:Object;
/**
* should be an object with name of the cookie variables parsed in as key/value pairs
*/
protected function set cookie(ck:Object):void{
_cookie = ck;
}
protected function get cookie():Object{
return _cookie;
}
public function AutoValidationURLRequest(){
};
public function send(url:String, postData:Object, generateUrlVars:Boolean = true):void{
if(generateUrlVars){
postData = convertToPostVars(postData);
}
sendRequest("http://yourwebsite.com"+url, postData, requestHeaders);
}
override protected function parseHeaders(e:HTTPStatusEvent):void{
super.parseHeaders(e);
if('Set-Cookie' in headers){
requestHeaders['Cookie'] = parseCookie(headers['Set-Cookie']);
//requestHeaders['User-Agent'] = headers['User-Agent'];
}
}
/**
* returns the cookie key/val string for send requests back to the server
*/
protected function parseCookie(cookieString:String):String{
var cookieObj:Object = new Object();
var cookieBits:Array = cookieString.split("; ");
return cookieBits[0];
/*
for each(var ck:String in cookieBits){
var cb:Array = ck.split("=");
cookieObj[cb[0]] = cb[1];
}
return cookieObj;
*/
}
}
}
HeaderURLRequest.as:
package libs
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import mx.core.FlexGlobals;
import mx.rpc.events.ResultEvent;
import mx.utils.ObjectUtil;
[Event("headerUrlRequestComplete")]
public class HeaderURLRequest extends EventDispatcher
{
public static const HEADERURLREQUEST_COMPLETE:String = "headerUrlRequestComplete";
public var headers:Array = [];
public var data:Object = new Object();
public var variables:Object = new Object();
public var invalidFields:Object = new Object();
public var errorMsg:String = "";
/**
* the headers array must contain an object with a 'name' key and a 'value' key eg: cookie: <cookieStr>
*/
public function HeaderURLRequest():void{
}
public function sendRequest(url:String, postData:Object = null, requestHeaders:Object = null):void{
var urlLoader:URLLoader = new URLLoader()
var urlRequest : URLRequest = new URLRequest(url);
//make it an ajax request
urlRequest.requestHeaders.push(new URLRequestHeader('X-Requested-With', 'XMLHttpRequest'));
for(var header:* in requestHeaders){
var authHeader:URLRequestHeader = new URLRequestHeader(header as String, requestHeaders[header]);
urlRequest.requestHeaders.push(authHeader)
}
var urlVariables:URLVariables = new URLVariables();
for (var vars:* in postData){
urlVariables[vars] = postData[vars];
}
urlRequest.method = URLRequestMethod.POST
urlRequest.data = urlVariables;
urlLoader.addEventListener(Event.COMPLETE, getData);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, parseHeaders);
urlLoader.load(urlRequest);
}
public function convertToPostVars(postData:Object, prependKeyName:String = ""):Object{
var params:Object = {};
if(prependKeyName == ""){
params['_method'] = 'POST';
}
for (var item:* in postData){
var objtype:Object = ObjectUtil.getClassInfo(postData[item]);
if(objtype.name == "Object"){
var modelKeyName:String = prependKeyName+"["+item+"]";
var subParams:Object = convertToPostVars(postData[item],modelKeyName);
params = merge(params, subParams);
}else{
params["data"+prependKeyName+"["+item+"]"] = postData[item];
}
}
return params;
}
public function flashErrorMsg():String{
var err:String = errorMsg;
errorMsg = "";
return err;
}
protected function parseHeaders(e:HTTPStatusEvent):void{
var i:Number=0;
headers = [];
for each(var header:URLRequestHeader in e.responseHeaders){
headers[header.name] = header.value;
i++;
}
}
protected function getData(e:Event):void{
//trace('data: ');
if(e.currentTarget.data == ''){
e.currentTarget.data = '{}';
}
data = JSON.parse(e.currentTarget.data);
//trace(ObjectUtil.toString(data));
if(data.hasOwnProperty('variables')){
variables = data.variables;
if (variables != null){
if(variables.hasOwnProperty('invalidFields')){
invalidFields = variables.invalidFields;
for (var error:String in invalidFields){
errorMsg += invalidFields[error] + "\n\n";
}
}
}else{
//no variable data found!!
}
}
dispatchEvent(new Event(HEADERURLREQUEST_COMPLETE));
}
public function isEmpty(obj:Object){
var isEmpty:Boolean = true;
for (var n in obj) { isEmpty = false; break; }
return isEmpty;
}
public function merge( obj0:Object, obj1:Object ):Object
{
var obj:Object = { };
for( var p:String in obj0 )
{
obj[ p ] = ( obj1[ p ] != null ) ? obj1[ p ] : obj0[ p ];
//trace( p, ' : obj0', obj0[ p ], 'obj1', obj1[ p ], '-> new value = ', obj[ p ] );
}
for (var p1:String in obj1){
if(!obj.hasOwnProperty(p1)){
obj[ p1 ] = obj1[ p1 ] ;
}
}
return obj;
}
}
}
Also, using this with my forked version of Jose Gonzalez's CakePHP ajax_controller plugin is really handy. It basically takes any Ajax Request and converts all view variables and outputs them into a JSON object, no rendered view. Otherwise, if you're not using an ajax request, Cake will render the views normally. Good Luck!
I am very new to Flex. I want to retrieve file's binary content using flex but failed. Here is the code so far:
// ActionScript file
package source.fileApi{
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.utils.setTimeout;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.events.IOErrorEvent;
import flash.events.Event;
import flash.utils.ByteArray;
import mx.utils.URLUtil;
public class FileAPIMain {
private var debug:Boolean = false;
private var dataReaded:String;
private var fr:FileReference;
public function FileAPIMain():void{
ExternalInterface.addCallback("setDebug", setDebug);
ExternalInterface.addCallback("onLoadFileClick", onLoadFileClick);
ExternalInterface.call("FileReader.__onFlashInitialized");
}
public function log(message:String):void {
if (debug) {
ExternalInterface.call("FileReader.__log", encodeURIComponent("[FileReader] " + message));
}
}
public function setDebug(val:Boolean):void {
debug = val;
if (val) {
log("debug enabled");
}
}
public function onLoadFileClick():void{
//create the FileReference instance
fr = new FileReference();
//listen for when they select a file
fr.addEventListener(Event.SELECT, onFileSelect);
//listen for when then cancel out of the browse dialog
fr.addEventListener(Event.CANCEL,onCancel);
//open a native browse dialog that filters for text files
fr.browse();
}
private function onFileSelect(e:Event):void{
fr.removeEventListener(Event.SELECT, onFileSelect);
//listen for when the file has loaded
fr.addEventListener(Event.COMPLETE, onLoadComplete);
//listen for any errors reading the file
fr.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
//load the content of the file
fr.load();
}
private function onCancel(e:Event):void{
log("File Browse Canceled");
fr = null;
}
private function onLoadComplete(e:Event):void{
fr.removeEventListener(Event.COMPLETE, onLoadComplete);
//get the data from the file as a ByteArray
var data:ByteArray = fr.data as ByteArray;
dataReaded = data.readUTFBytes(data.bytesAvailable);
ExternalInterface.call("FileReader.__getSize", fr.size);
ExternalInterface.call("FileReader.__getName", fr.name);
ExternalInterface.call("FileReader.__getData", dataReaded);
ExternalInterface.call("FileReader.__takeAction");
//clean up the FileReference instance
fr = null;
}
private function onLoadError(e:IOErrorEvent):void{
log("Error loading file : " + e.text);
}
}
}
But this did not give me the binary content of the file.. Could any one please tell me how to retrieve the full binary content of the given file using Flex (I am using FP 10.0).....
If you user FLashPlayer 10+ then make use of FileReference.
See the pure AS3 sample below
var buttonShape:Shape = new Shape();
buttonShape.graphics.beginFill(0x336699);
buttonShape.graphics.drawCircle(50, 50, 25);
var button = new SimpleButton(buttonShape, buttonShape, buttonShape, buttonShape);
addChild(button);
var fileRef:FileReference= new FileReference();
button.addEventListener(MouseEvent.CLICK, onButtonClick);
function onButtonClick(e:MouseEvent):void
{
fileRef.browse([new FileFilter("Images", "*.jpg;*.gif;*.png")]);
fileRef.addEventListener(Event.SELECT, onFileSelected);
}
function onFileSelected(e:Event):void
{
fileRef.addEventListener(Event.COMPLETE, onFileLoaded);
fileRef.load();
}
function onFileLoaded(e:Event):void
{
// here we get the data
var theData:Object = e.target.data;
// next you can manipulate the data as you like! ;) depending on the type
}
I have taken this code from one of my friend,but in real it is totally mess there are plenty of error i am getting by running this code,i have some question
How i can use this code in mxml application,as we know we can not use public class in mx script so what are the way to do that
as you can see .mx_internal,i am getting error on that saying'define object before dot' as i remove mx_internal and tried using import mx.binding.mx_internal and use namespace mx_internal application not desplaying anything
now you will tell me ther are easy methods are ther to solve problem but my whole project is on this method only
thanks for help in advance
i am trying to solve this problem from last 15 days ,with no success,pls help me below is code
package components
{
import flash.events.*;
import flash.utils.*;
import mx.binding.*;
import mx.containers.*;
import mx.controls.*;
import mx.core.*;
import mx.events.*;
import mx.styles.*;
public class DialogTitle extends HBox implements IBindingClient
{
private var _110371416title:String = "Dialog Title";
public var _DialogTitle_Image1:Image;
public var _DialogTitle_Image2:Image;
public var _DialogTitle_Label1:Label;
var _bindingsBeginWithWord:Object;
private var _1859425293showCloseButton:Boolean = false;
var _bindingsByDestination:Object;
var _watchers:Array;
var _bindings:Array;
private var _documentDescriptor_:UIComponentDescriptor;
private static var _watcherSetupUtil:IWatcherSetupUtil;
public function DialogTitle()
{
_documentDescriptor_ = new UIComponentDescriptor({type:HBox, propertiesFactory:function () : Object
{
return {height:27, childDescriptors:[new UIComponentDescriptor({type:Spacer, propertiesFactory:function () : Object
{
return {width:5};
}// end function
}), new UIComponentDescriptor({type:Image, id:"_DialogTitle_Image1"}), new UIComponentDescriptor({type:Spacer, propertiesFactory:function () : Object
{
return {width:5};
}// end function
}), new UIComponentDescriptor({type:Label, id:"_DialogTitle_Label1", stylesFactory:function () : void
{
this.fontSize = 14;
this.color = 16777215;
this.fontWeight = "bold";
return;
}// end function
}), new UIComponentDescriptor({type:Spacer, propertiesFactory:function () : Object
{
return {percentWidth:100};
}// end function
}), new UIComponentDescriptor({type:Image, id:"_DialogTitle_Image2", events:{click:"___DialogTitle_Image2_click"}, propertiesFactory:function () : Object
{
return {useHandCursor:true, buttonMode:true, mouseChildren:false, toolTip:"Close"};
}// end function
}), new UIComponentDescriptor({type:Spacer, propertiesFactory:function () : Object
{
return {width:13};
}// end function
})]};
}// end function
});
_bindings = [];
_watchers = [];
_bindingsByDestination = {};
_bindingsBeginWithWord = {};
mx_internal::_document = this;
if (!this.styleDeclaration)
{
this.styleDeclaration = new CSSStyleDeclaration();
}
this.styleDeclaration.defaultFactory = function () : void
{
this.backgroundColor = 9947478;
this.horizontalGap = 0;
this.verticalAlign = "middle";
this.verticalGap = 0;
return;
}// end function
;
this.height = 27;
this.percentWidth = 100;
return;
}// end function
private function _DialogTitle_bindingExprs() : void
{
var _loc_1:* = undefined;
_loc_1 = CustomEmbeddedAssets.logoImageSmall;
_loc_1 = title;
_loc_1 = EmbeddedAssets.dialogClose;
_loc_1 = showCloseButton;
return;
}// end function
public function get showCloseButton() : Boolean
{
return this._1859425293showCloseButton;
}// end function
override public function initialize() : void
{
var target:DialogTitle;
var watcherSetupUtilClass:Object;
.mx_internal::setDocumentDescriptor(_documentDescriptor_);
var bindings:* = _DialogTitle_bindingsSetup();
var watchers:Array;
target;
if (_watcherSetupUtil == null)
{
watcherSetupUtilClass = getDefinitionByName("_components_DialogTitleWatcherSetupUtil");
var _loc_2:* = watcherSetupUtilClass;
_loc_2.watcherSetupUtilClass["init"](null);
}
_watcherSetupUtil.setup(this, function (param1:String)
{
return target[param1];
}// end function
, bindings, watchers);
var i:uint;
while (i < bindings.length)
{
Binding(bindings[i]).execute();
i = (i + 1);
}
mx_internal::_bindings = mx_internal::_bindings.concat(bindings);
mx_internal::_watchers = mx_internal::_watchers.concat(watchers);
super.initialize();
return;
}// end function
public function get title() : String
{
return this._110371416title;
}// end function
private function _DialogTitle_bindingsSetup() : Array
{
var binding:Binding;
var result:Array;
binding = new Binding(this, function () : Object
{
return CustomEmbeddedAssets.logoImageSmall;
}// end function
, function (param1:Object) : void
{
_DialogTitle_Image1.source = param1;
return;
}// end function
, "_DialogTitle_Image1.source");
result[0] = binding;
binding = new Binding(this, function () : String
{
var _loc_1:* = title;
var _loc_2:* = _loc_1 == undefined ? (null) : (String(_loc_1));
return _loc_2;
}// end function
, function (param1:String) : void
{
_DialogTitle_Label1.text = param1;
return;
}// end function
, "_DialogTitle_Label1.text");
result[1] = binding;
binding = new Binding(this, function () : Object
{
return EmbeddedAssets.dialogClose;
}// end function
, function (param1:Object) : void
{
_DialogTitle_Image2.source = param1;
return;
}// end function
, "_DialogTitle_Image2.source");
result[2] = binding;
binding = new Binding(this, function () : Boolean
{
return showCloseButton;
}// end function
, function (param1:Boolean) : void
{
_DialogTitle_Image2.visible = param1;
return;
}// end function
, "_DialogTitle_Image2.visible");
result[3] = binding;
return result;
}// end function
public function set showCloseButton(param1:Boolean) : void
{
var _loc_2:* = this._1859425293showCloseButton;
if (_loc_2 !== param1)
{
this._1859425293showCloseButton = param1;
this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "showCloseButton", _loc_2, param1));
}
return;
}// end function
public function ___DialogTitle_Image2_click(event:MouseEvent) : void
{
dispatchEvent(new Event("onCancel"));
parent.visible = false;
return;
}// end function
public function set title(param1:String) : void
{
var _loc_2:* = this._110371416title;
if (_loc_2 !== param1)
{
this._110371416title = param1;
this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "title", _loc_2, param1));
}
return;
}// end function
public static function set watcherSetupUtil(param1:IWatcherSetupUtil) : void
{
DialogTitle._watcherSetupUtil = param1;
return;
}// end function
}
}
Just throw this code out. This code was generated automatically by mxmlc compiler from MXML class and can't be used in production. It is for computer, not for humans. Write the right code by yourself. I hope it will be clearer and maintainable. And yes, this code wasn't written by your friend :)
This file is decompiled from a .mxml file, which use tags to describe layout. However, some decompiler can't convert it completely, and you will see file like this.
As you see, the argument of UIComponentDescriptor is an object, which contains a lot of key-val pairs. It has some type of keys:
type:Class --> this is the type of this component, which is the node tag of .mxml file
id:String --> this is the ID of a node, which is also the variable name you can use in <fx:Script> tag
event:Object --> events that the component will trigger
stylesFactory:Function --> component's styles setting
propertiesFactory:Function --> contains some properties and child nodes
code like this:
<mx:Canvas id="mainCanvas" borderStyle="none" label="main">
<mx:Button click="onClick(event)" />
</mx:Canvas>
will be converted into:
new UIComponentDescriptor({
"type":Canvas,
"id":mainCanvas,
"styleFactory":function():void {
this.borderStyle="none";
},
"propertiesFactory":function():Object {
return({
"label":"main"
"childDescriptors":[new UIComponentDescriptor({
// button's code in here
});
]
})
}
})
For those events:
As you can write click event in mxml tags both like btnOnClick() and btnOnClick(event), the compiler need to do something to ensure the event handler accept a right argument. So, for the Button tag I just mention, the
value corresponding to key"event" will be like this: {"click":"__on_click"}. Then the compiler will create a new function call __on_click, which may like this:
public function __on_click(event:MouseEvent):void {
onClick(event);
}
Obviously, after you convert the UIComponentDescriptor into .mxml, you should replace the events function.
For the constructor:
.mxml file can not has a constructor, but the compiler will create one in .as file, which contains the UIComponentDescriptor. The constructor will also do some initialization for it's variables. When converting to .mxml file, you need to do this initialization after the variable's declaration.
For example:
public function MyCanvas(){
this._documentDescriptor_ = new UIComponentDescriptor({
//……
});
this.myArray = new Array();
}
you should convert it into this:
<fx:Script><![CDATA[
var myArray:Array = new Array();
]]></fx:Script>
So the heaviest work is to convert UIComponentDescriptor into .mxml tags. And here is a simple python script that can help you do it:
UIComponentDescriptor2XML
In my AIR app, I am trying to implement a file downloader using URLStream.
public class FileDownloader {
// Class to download files from the internet
// Function called every time data arrives
// called with an argument of how much has been downloaded
public var onProgress :Function = function(loaded:Number, total:Number):void{};
public var onComplete :Function = function():void{};
public var remotePath :String = "";
public var localFile :File = null;
public var running:Boolean = false;
public var stream :URLStream;
private var fileAccess :FileStream;
public function FileDownloader( remotePath :String = "" , localFile :File = null ) {
this.remotePath = remotePath;
this.localFile = localFile;
}
public function load() :void
{
try
{
stream = null;
if( !stream || !stream.connected )
{
stream = new URLStream();
fileAccess = new FileStream();
var requester :URLRequest = new URLRequest( remotePath );
var currentPosition :uint = 0;
var downloadCompleteFlag :Boolean = false;
// Function to call oncomplete, once the download finishes and
// all data has been written to disc
fileAccess.addEventListener( "outputProgress", function ( result ):void {
if( result.bytesPending == 0 && downloadCompleteFlag ) {
stream.close();
fileAccess.close();
running = false;
onComplete();
}
});
fileAccess.openAsync( localFile, FileMode.WRITE );
fileAccess.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent)
{
trace('remotePath: '+remotePath);
trace('io error while wrintg ....'+e.toString());
});
stream.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent)
{
trace('remotePath: '+remotePath);
trace('There was an IO error with the stream: '+e.text);
});
stream.addEventListener( "progress" , function (e:ProgressEvent) :void {
var bytes :ByteArray = new ByteArray();
var thisStart :uint = currentPosition;
currentPosition += stream.bytesAvailable;
// ^^ Makes sure that asyncronicity does not break anything
try
{
//trace('reading from '+remotePath+' ...');
stream.readBytes( bytes, thisStart );
fileAccess.writeBytes( bytes, thisStart );
}
catch(err:Error)
{
trace('remotePath: '+remotePath);
trace('error while writing bytes from...'+err.name+':'+err.message);
if(stream.connected)
stream.close();
abort();
onComplete();
return;
}
onProgress( e.bytesLoaded, e.bytesTotal );
});
stream.addEventListener( "complete", function () :void {
downloadCompleteFlag = true;
});
stream.load( requester );
} else {
// Do something unspeakable
}
running = true;
}
catch(err:Error)
{
trace('error while downloading the file: '+err);
}
}
public function abort():void {
try {
stream.close();
trace('stream closed');
running = false;
}
catch(err:Error) {
trace('error while aborting download');
trace(err);
}
}
}
I simply create an object of the above class and passing the url and the file and call the load function. For some files I get the following error.
remotePath: http://mydomain.com/238/6m_608-450.jpg
error while writing bytes from...Error:Error #2029: This URLStream object does not have a stream opened.
Which means the error is from the file stream(fileAccess) that I am using. I am unable to figure out why this could be happening. If I try to open the url http://mydomain.com/238/6m_608-450.jpg in the browser, it opens properly. This happens randomly for some files. What could be the problem?
I have tried in my office and it works for me (for differents files and filesize).
So, can you describe the files (or types files) which don't work for you (post an url if you can) ?
I would say that when you use the method readBytes your stream (so the URLStream) is ever close.
More, I allows me some advice :
1/ Use flash's constants instead of simple string
2/ Don't forget to remove your listeners once the operation completed
3/ Your method FileDownloader is quite confusing. Use lowercase if it's a function or puts a capital letter with class's name if you use it as a constructor. For me, this function must be a constructor.
Hello the problem i'm experiencing is when I attempt to call javascript function.
Using Jquery #
$("#flashtxtchat").get(0).startTxtChat()
ArgumentError: Error #2126:
NetConnection object must be
connected. at
flash.net::NetConnection/get nearID()
at textchat/startChat() at
Function/http://adobe.com/AS3/2006/builtin::apply()
at
flash.external::ExternalInterface$/_callIn()
at ()
List item
<![CDATA[
import flash.events.*;
import flash.external.*;
import flash.net.*;
import flash.system.*;
import mx.containers.*;
import mx.controls.*;
import mx.core.*;
import mx.events.*;
import mx.styles.*;
import mx.utils.*;
private var netConnection:NetConnection;
private var sendStream:NetStream;
private var receiveStream:NetStream;
private var strangerPeerID:String;
public function init() : void
{
var url:* = FlexGlobals.topLevelApplication.url;
var serverName:* = URLUtil.getServerName(url);
if (!serverName.match(/(localhost|127.0.0.1)$/))
{
return;
}
ExternalInterface.addCallback("startTxtChat", this.startChat);
ExternalInterface.addCallback("gotStrangerPeerID", this.gotStrangerPeerID);
ExternalInterface.addCallback("sendMsg", this.sendMsg);
ExternalInterface.addCallback("stopTxtChat", this.stopChat);
ExternalInterface.call("flashtxtChat_init");
return;
}// end function
public function startChat() : void
{
if (this.netConnection)
{
ExternalInterface.call("flashtxtChat_gotNearID", this.netConnection.nearID);
}
else
{
this.netConnection = new NetConnection();
this.netConnection.addEventListener(NetStatusEvent.NET_STATUS, this.netConnectionHandler);
this.netConnection.connect("rtmfp://stratus.rtmfp.net/removed-removed/");
}
return;
}// end function
public function gotStrangerPeerID(param1:String) : void
{
var _loc_3:NetStream = null;
this.strangerPeerID = param1;
var _loc_2:int = 0;
while (_loc_2 < this.sendStream.peerStreams.length)
{
_loc_3 = this.sendStream.peerStreams[_loc_2];
if (_loc_3.farID != this.strangerPeerID)
{
_loc_3.close();
}
_loc_2++;
}
this.receiveStream = new NetStream(this.netConnection, this.strangerPeerID);
this.receiveStream.play("textchat");
this.receiveStream.client = this;///temp added by me
//this.strangerVideo.attachNetStream(this.receiveStream);
return;
}// end function
public function sendMsg(msg: String) : void
{
sendStream.send("recvMsg", msg);
}
public function recvMsg(msg: String) : void
{
ExternalInterface.call("recvMsg", msg);
}
public function stopChat() : void
{
this.strangerPeerID = null;
return;
}// end function
public function netConnectionHandler(event:NetStatusEvent) : void
{
var c:Object;
var event:* = event;
switch(event.info.code)
{
case "NetConnection.Connect.Success":
{
c = new Object();
c.onPeerConnect = function (param1:NetStream) : Boolean
{
if (strangerPeerID == null)
{
return true;
}
return param1.farID == strangerPeerID;
};// end function
this.sendStream = new NetStream(this.netConnection, NetStream.DIRECT_CONNECTIONS);
this.sendStream.client = c;
this.sendStream.publish("textchat");
ExternalInterface.call("flashtxtChat_gotNearID", this.netConnection.nearID);
break;
}
case "NetConnection.Connect.Failed":
{
this.netConnection = null;
ExternalInterface.call("flashCb_errorConnectingToStratus");
break;
}
case "NetConnection.Connect.Closed":
{
this.netConnection = null;
this.sendStream.close();
this.sendStream = null;
if (this.receiveStream)
{
this.receiveStream.close();
this.receiveStream = null;
}
break;
}
default:
{
break;
}
}
return;
}// end function
]]>
</mx:Script>
What can be the problem? Thank you I've used a similar implementation for video chat which works flawlessly I just removed all video related functions and only left in text chat now it doesn't work?
check player settings they reset after update allow local p2p