Loading external data

OpenFL includes mechanisms for loading data from external sources. Those sources can provide static content such as text files, or dynamic content generated by a web server backend script. The data can be formatted in various ways, and OpenFL provides functionality for decoding and accessing the data. You can also send data to the external server as part of the process of retrieving data.

Using the URLRequest class

Many APIs that load external data use the URLRequest class to define the properties of necessary network request.

URLRequest properties

You can set the following properties of a URLRequest object in any security sandbox:

Property Description
contentType The MIME content type of any data sent with the URL request. If no contentType is set, values are sent as application/x-www-form-urlencoded.
data An object containing data to be transmitted with the URL request.
method The HTTP request method, such as a GET or POST.
requestHeaders The array of HTTP request headers to be appended to the HTTP request. Note that permission to set some headers is restricted on some targets.
url Specifies the URL to be requested.

On OpenFL native targets, you can set additional properties of the URLRequest class.

Property Description
followRedirects Specifies whether redirects are to be followed (true, the default value) or not (false).
manageCookies Specifies whether the HTTP protocol stack should manage cookies (true, the default value) or not (false) for this request.
authenticate Specifies whether authentication requests should be handled (true) for this request. The default is to authenticate requests—which may cause an authentication dialog box to be displayed if the server requires credentials. You can also set the user name and password using the URLRequestDefaults class—see Setting URLRequest defaults.
userAgent Specifies the user-agent string to be used in the HTTP request.

Setting URLRequest defaults

The URLRequestDefaults class lets you define application-specific default settings for URLRequest objects. For example, the following code sets the default values for the manageCookies and useCache properties. All new URLRequest objects will use the specified values for these properties instead of the normal defaults:

URLRequestDefaults.manageCookies = false;
URLRequestDefaults.useCache = false;

For more information, see the URLRequestDefaults class listing in the OpenFL API Reference.

URI schemes

The standard URI schemes, such as the following, can be used in requests made from any security sandbox:

http: and https:

Use these for standard Internet URLs (in the same way that they are used in a web browser).

file:

Use file: to specify the URL of a file located on the local file system. For example:

file:///c:/AIR Test/test.txt

In AIR, you can also use the following schemes when defining a URL for content running in the application security sandbox:

app:

Use app: to specify a path relative to the root directory of the installed application. For example, the following path points to a resources subdirectory of the directory of the installed application:

app:/resources

The URL (and url property) for a File object created with File.applicationDirectory may use the app URI scheme, as in the following:

var dir:File = File.applicationDirectory;
dir = dir.resolvePath("assets");
trace(dir.url); // app:/assets

app-storage:

Use app-storage: to specify a path relative to the data storage directory of the application. For each installed application (and user), AIR creates a unique application storage directory, which is a useful place to store data specific to that application. For example, the following path points to a prefs.xml file in a settings subdirectory of the application store directory:

app-storage:/settings/prefs.xml

The URL (and url property) for a File object created with File.applicationStorageDirectory may use the app-storage URI scheme, as in the following:

var prefsFile:File = File.applicationStorageDirectory;
prefsFile = prefsFile.resolvePath("prefs.xml");
trace(dir.prefsFile); // app-storage:/prefs.xml

You can use a URLRequest object that uses any of these URI schemes to define the URL request for a number of different objects, such as a FileStream or a Sound object.

Setting URL variables

While you can add variables to the URL string directly, it can be easier to use the URLVariables class to define any variables needed for a request.

There are three ways in which you can add parameters to a URLVariables object:

  • Within the URLVariables constructor

  • With the URLVariables.decode() method

  • As dynamic properties of the URLVariables object itself

The following example illustrates all three methods and also how to assign the variables to a URLRequest object:

import openfl.display.Sprite;
import openfl.net.URLRequest;
import openfl.net.URLVariables;
import openfl.Lib;

class URLVariablesExample extends Sprite {
    public function new() {
        super();

        var urlVar:URLVariables = new URLVariables("one=1&two=2");
        urlVar.decode("amp=" + Lib.encodeURIComponent("&") );
        urlVar.three = 3;
        urlVar.amp2 = "&&";
        trace(Std.string(urlVar)); //amp=%26&amp2=%26%26&one=1&two=2&three=3

        var urlRequest:URLRequest = new URLRequest("http://www.example.com/test/");
        urlRequest.data = urlVar;
    }
}

When you define variables within the URLVariables constructor or within the URLVariables.decode() method, make sure that you URL-encode the characters that have a special meaning in a URI string. For example, when you use an ampersand in a parameter name or value, you must encode the ampersand by changing it from & to %26 because the ampersand acts as a delimiter for parameters. The top-level encodeURIComponent() function can be used for this purpose.

Using the URLLoader class

The URLLoader class let you send a request to a server and access the information returned. You can also use the URLLoader class to access files on the local file system in contexts where local file access is permitted. The URLLoader class downloads data from a URL as text, binary data, or URL-encoded variables. The URLLoader class dispatches events such as complete, httpStatus, ioError, open, progress, and securityError.

For more information on handling events in OpenFL, see Handling events

Downloaded data is not available until the download has completed. You can monitor the progress of the download (bytes loaded and bytes total) by listening for the progress event to be dispatched. However, if a file loads quickly enough a progress event might not be dispatched. When a file has successfully downloaded, the complete event is dispatched. By setting the URLLoader dataFormat property, you can receive the data as text, raw binary data, or as a URLVariables object.

The URLLoader.load() method (and optionally the URLLoader class's constructor) takes a single parameter, request, which is a URLRequest object. A URLRequest object contains all of the information for a single HTTP request, such as the target URL, request method (GET or POST), additional header information, and the MIME type.

For example, to upload an XML packet to a server-side script, you could use the following code:

import openfl.display.Sprite;
import openfl.net.URLLoader;
import openfl.net.URLRequest;
import openfl.net.URLRequestMethod;

class URLLoaderPostExample extends Sprite {
    public function new() {
        super();

        var secondsUTC:Float = Date.now().getTime();
        var dataXML:Xml = Xml.parse('<clock>
                <time>$secondsUTC</time>
            </clock>');

        var request:URLRequest = new URLRequest("http://www.example.com/time/");
        request.contentType = "text/xml";
        request.data = Std.string(dataXML);
        request.method = URLRequestMethod.POST;

        var loader:URLLoader = new URLLoader();
        loader.load(request);
    }
}

The previous snippet creates an XML document named dataXML that contains the XML packet to be sent to the server. The example sets the URLRequest contentType property to "text/xml" and assigns the XML document to the URLRequest data property. Finally, the example creates a URLLoader object and sends the request to the remote script by using the load() method.

Using the URLStream class

The URLStream class provides access to the downloading data as the data arrives. The URLStream class also lets you close a stream before it finishes downloading. The downloaded data is available as raw binary data.

When reading data from a URLStream object, use the bytesAvailable property to determine whether sufficient data is available before reading it. An EOFError exception is thrown if you attempt to read more data than is available.

The httpResponseStatus event

On some targets, the URLStream class dispatches an httpResponseStatus event in addition to the httpStatus event. The httpResponseStatus event is delivered before any response data. The httpResponseStatus event (represented by the HTTPStatusEvent class) includes a responseURL property, which is the URL that the response was returned from, and a responseHeaders property, which is an array of URLRequestHeader objects representing the response headers that the response returned.

Loading data from external documents

When you build dynamic applications, it can be useful to load data from external files or from server-side scripts. This lets you build dynamic applications without having to edit or recompile your application. For example, if you build a "tip of the day" application, you can write a server-side script that retrieves a random tip from a database and saves it to a text file once a day. Then your application can load the contents of a static text file instead of querying the database each time.

The following snippet creates a URLRequest and URLLoader object, which loads the contents of an external text file, params.txt:

var request:URLRequest = new URLRequest("params.txt");
var loader:URLLoader = new URLLoader();
loader.load(request);

By default, if you do not define a request method, OpenFL loads the content using the HTTP GET method. To send the request using the POST method, set the request.method property to POST using the static constant URLRequestMethod.POST, as the following code shows:

var request:URLRequest = new URLRequest("https://www.example.com/sendfeedback/");
request.method = URLRequestMethod.POST;

The external document, params.txt, that is loaded at run time contains the following data:

monthNames=January,February,March,April,May,June,July,August,September,October,November,December&dayNames=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday

The file contains two parameters, monthNames and dayNames. Each parameter contains a comma-separated list that is parsed as strings. You can split this list into an array using the String.split() method.

Avoid using reserved words or language constructs as variable names in external data files, because doing so makes reading and debugging your code more difficult.

Once the data has loaded, the complete event is dispatched, and the contents of the external document are available to use in the URLLoader's data property, as the following code shows:

function completeHandler(event:Event):Void
{
    var loader2:URLLoader = cast(event.target, URLLoader);
    trace(loader2.data);
}

If the remote document contains name-value pairs, you can parse the data using the URLVariables class by passing in the contents of the loaded file, as follows:

private function completeHandler(event:Event):void
{
    var loader2:URLLoader = cast(event.target, URLLoader);
    var variables:URLVariables = new URLVariables(loader2.data);
    trace(variables.dayNames);
}

Each name-value pair from the external file is created as a property in the URLVariables object. Each property within the variables object in the previous code sample is treated as a string. If the value of the name-value pair is a list of items, you can convert the string into an array by calling the String.split() method, as follows:

var dayNameArray:Array = variables.dayNames.split(",");

If you are loading numeric data from external text files, convert the values into numeric values by using a top-level function, such as Std.parseInt() or Std.parseFloat().

Instead of loading the contents of the remote file as a string and creating a new URLVariables object, you could instead set the URLLoader.dataFormat property to one of the static properties found in the URLLoaderDataFormat class. The three possible values for the URLLoader.dataFormat property are as follows:

  • URLLoaderDataFormat.BINARY — The URLLoader.data property will contain binary data stored in a ByteArray object.

  • URLLoaderDataFormat.TEXT — The URLLoader.data property will contain text in a String object.

  • URLLoaderDataFormat.VARIABLES — The URLLoader.data property will contain URL-encoded variables stored in a URLVariables object.

The following code demonstrates how setting the URLLoader.dataFormat property to URLLoaderDataFormat.VARIABLES allows you to automatically parse loaded data into a URLVariables object:

import openfl.display.Sprite;
import openfl.events.*;
import openfl.net.URLLoader;
import openfl.net.URLLoaderDataFormat;
import openfl.net.URLRequest;

class URLLoaderDataFormatExample extends Sprite {
    public function new()
    {
        super();

        var request:URLRequest = new URLRequest("http://www.example.com/params.txt");
        var variables:URLLoader = new URLLoader();
        variables.dataFormat = URLLoaderDataFormat.VARIABLES;
        variables.addEventListener(Event.COMPLETE, completeHandler);
        try
        {
            variables.load(request);
        }
        catch (error:Error)
        {
            trace("Unable to load URL: " + error);
        }
    }
    private function completeHandler(event:Event):Void
    {
        var loader:URLLoader = URLLoader(event.target);
        trace(loader.data.dayNames);
    }
}

Note: The default value for URLLoader.dataFormat is URLLoaderDataFormat.TEXT.

As the following example shows, loading XML from an external file is the same as loading URLVariables. You can create a URLRequest instance and a URLLoader instance and use them to download a remote XML document. When the file has completely downloaded, the Event.COMPLETE event is dispatched and the contents of the external file are converted to an XML instance, which you can parse using XML methods and properties.

import openfl.display.Sprite;
import openfl.errors.*;
import openfl.events.*;
import openfl.net.URLLoader;
import openfl.net.URLRequest;

class ExternalDocs extends Sprite
{
    public function new()
    {
        super();

        var request:URLRequest = new URLRequest("http://www.example.com/data.xml");
        var loader:URLLoader = new URLLoader();
        loader.addEventListener(Event.COMPLETE, completeHandler);
        try
        {
            loader.load(request);
        }
        catch (error:ArgumentError)
        {
            trace("An ArgumentError has occurred.");
        }
        catch (error:SecurityError)
        {
            trace("A SecurityError has occurred.");
        }
        catch (error:Dynamic)
        {
            trace("An unknown has occurred.");
        }
    }
    private function completeHandler(event:Event):Void
    {
        var dataXML:Xml = Xml.parse(event.target.data);
        trace(Std.string(dataXML));
    }
}

Communicating with external scripts

In addition to loading external data files, you can also use the URLVariables class to send variables to a server-side script and process the server's response. This is useful, for example, if you are programming a game and want to send the user's score to a server to calculate whether it should be added to the high scores list, or even send a user's login information to a server for validation. A server-side script can process the user name and password, validate it against a database, and return confirmation of whether the user-supplied credentials are valid.

The following snippet creates a URLVariables object named variables, which creates a new variable called name. Next, a URLRequest object is created that specifies the URL of the server-side script to send the variables to. Then you set the method property of the URLRequest object to send the variables as an HTTP POST request. To add the URLVariables object to the URL request, you set the data property of the URLRequest object to the URLVariables object created earlier. Finally, the URLLoader instance is created and the URLLoader.load() method is invoked, which initiates the request.

import openfl.display.Sprite;
import openfl.events.Event;
import openfl.net.URLLoader;
import openfl.net.URLLoaderDataFormat;
import openfl.net.URLRequest;
import openfl.net.URLRequestMethod;
import openfl.net.URLVariables;

class GreetingExample extends Sprite {
    public function new() {
        super();

        var variables:URLVariables = new URLVariables("name=Franklin");
        var request:URLRequest = new URLRequest();
        request.url = "http://www.example.com/greeting.php";
        request.method = URLRequestMethod.POST;
        request.data = variables;
        var loader:URLLoader = new URLLoader();
        loader.dataFormat = URLLoaderDataFormat.VARIABLES;
        loader.addEventListener(Event.COMPLETE, completeHandler);
        try
        {
            loader.load(request);
        }
        catch (error:Dynamic)
        {
            trace("Unable to load URL");
        }
    }

    function completeHandler(event:Event):Void
    {
        trace(event.target.data.welcomeMessage);
    }
}

The following code contains the contents of the PHP greeting.php document used in the previous example:

<?php
    $name = "Stranger";
    if (!empty($_REQUEST["name"])) {
        $name = $_REQUEST["name"];
    }
    $message = "Welcome, $name";
?>
welcomeMessage=<?=urlencode($message)?>

results matching ""

    No results matching ""