Recipe 23.1.
Downloading Files
Problem
You want
to let users download files
to their computer.
Solution
Use the download( ) method of a
FileReference object.
Discussion
The flash.net.FileReference class
defines a download( ) method that allows users to download a
file from a URL to their computers. When Flash Player calls the
download( ) method, it attempts to open a dialog box, titled
"Select location for download." This dialog box allows users to use
a standard operating system dialog to browse their local disks for
a location to which they want to save files.
The first step before calling the download(
) method is to construct a FileReference object, as
follows:
var fileReference:FileReference = new FileReference( );
The download( ) method requires at least
one parameter as a URLRequest object, specifying the URL
from which you want to download the file. In the simplest case, the
URL points to a static file that the user can download. The
following example opens a save dialog box that allows users to
select a location to which they can save a copy of
example.txt from the same directory on the server where the
SWF resides:
var urlRequest:URLRequest = new URLRequest("example.txt");
fileReference.download(urlRequest);
Specifying a full path to a file is as simple as
specifying the URL when constructing the URLRequest object,
as the following example illustrates:
var urlRequest:URLRequest = new URLRequest("http://www.myexamplesite.com/example.txt");
fileReference.download(urlRequest);
The save
dialog box also allows users to change the name of the file they're
downloading. By default, the filename field displays the name of
the file as it exists on the server. In the preceding example, the
filename field in the save dialog box displays example.txt.
In many cases, though, you may want to use a different default name
than the name of the file specified in the URL. For example, if a
static file was created by a server-side script, it may have a
unique identifier name as its filename (e.g.,
R7AS82892KHWI014.jpg) that you may not want to display to
users by default. Additionally, there are cases when the file is
created dynamically at request time by a script, and the
URLRequest object points to that script. In those cases, the
default value for the filename field in the save dialog box is the
name of the script (e.g., script.cgi), which not only isn't
user-friendly, but it can cause the file to be misread by Windows
computers if it has the incorrect file extension.
The download( ) method accepts a second,
optional parameter by which you can specify a different default
value for the filename field in the save dialog box. The second
parameter is a string, the value of which is displayed in the
filename field. The following example prompts the user to download
a file that is created dynamically at request time by a script
(script.cgi). In this example, the script outputs a JPEG
image file. Rather than using the default filename value
(script.cgi), the code specifies a filename value of
example.jpg:
var urlRequest:URLRequest = new URLRequest("script.cgi");
fileReference.download(urlRequest, "example.jpg");
When working with the download( ) method,
it's important to use a try...catch statement because the
method can throw errors. If an error isn't handled properly, it can
cause things to malfunction (if the code assumes the operation was
successful) and can display a default error message to the user.
It's almost never a good idea to allow Flash Player to throw an
unhandled event that would display a default error message to the
user, as that would likely cause the user to feel as though
something has broken. Handling the error with ActionScript code
allows the application to respond to the error much more gracefully
than it would if the error were unhandled. The two most common
errors are IllegalOperationError and SecurityError.
The IllegalOperationError occurs when
you call download( ) and a save dialog box is already open;
only one such dialog box can be open at a time. The
SecurityError occurs when the SWF doesn't have permission to
download the file because the SWF is an untrusted file:
try {
fileReference.download(urlRequest, fileName);
}
catch (illegalOperation:IllegalOperationError) {
// code to handle an illegal operation error
}
catch (security:SecurityError) {
// code to handle a security error
}
Although less common, the download( )
method can also throw errors of type ArgumentError and MemoryError. ArgumentError errors occur when
the URL- Request parameter has a data property that isn't of
type URLVariables or String. Although your
URLRequest allows you to assign a byte array to the data
property, the download( ) method works only when the data
property is of type URLVariables of String. The
memory error is fairly obscure, and it can occur when one of two
conditions is present. If the URLRequest is set to make a
GET request and System.useCodePage is
true, Flash Player may not be able to convert characters
from Unicode to multibyte character format as required.
Alternatively, Flash Player may not be able to allocate the
necessary memory to open the save dialog box.
In addition to the errors that the download(
) method throws, it also dispatches error events. The
download( ) method dispatches a security error event of type
SecurityErrorEvent when Flash Player was unable to download
the file for security reasons. Security error events occur when
Flash Player's sandbox security doesn't grant the SWF permission to
download a file from the specified URL. The download( )
method can dispatch an I/O error event of type IOErrorEvent
when there is an error downloading the file due to one of the
following reasons:
-
A network error
-
The server requires authentication and Flash
Player isn't running in a browser
-
An invalid protocol (only HTTP, HTTPS, and FTP
work)
You must add an event listener to handle error
events such as SecurityErrorEvent and
IOErrorEvent. You can
add an event listener for an error event just as you would for a
standard event. The following example adds a listener for an
IOErrorEvent type.
fileReference.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
See Also
Recipe
23.2
|