处理文件上载和下载

可通过使用 FileReference 类,在客户端和服务器之间添加上载和下载文件的功能。将通过一个对话框(例如,Windows 操作系统中的“打开”对话框)提示用户选择要上载的文件或用于下载的位置。

使用 ActionScript 创建的每个 FileReference 对象都引用用户硬盘上的一个文件。该对象的属性包含有关文件大小、类型、名称、创建日期和修改日期的信息。

注意

 

仅 Mac OS 支持 creator 属性。所有其它平台都会返回 null

可以通过两种方式创建 FileReference 类的实例。可以使用 new 运算符,如以下代码所示:

import flash.net.FileReference;
var myFileReference:FileReference = new FileReference();

或者,可以调用 FileReferenceList.browse() 方法,该方法在用户的系统中打开一个对话框,提示用户选择一个或多个要上载的文件,如果用户成功选择了一个或多个文件,将创建一个由 FileReference 对象组成的数组。每个 FileReference 对象表示用户在对话框中选择的一个文件。FileReference 对象在 FileReference 属性(例如 namesizemodificationDate)中不包含任何数据,直到发生下列任一情况:

注意

 

当执行下载时,在下载完成前只填充 FileReference.name 属性。下载完文件后,所有属性都将可用。

在执行对 FileReference.browse()FileReferenceList.browse()FileReference.download() 方法的调用时,大多数播放器将继续 SWF 文件播放。

子主题

FileReference 类
将文件上载到服务器
从服务器下载文件
FileReferenceList 类

FileReference 类

使用 FileReference 类可以在用户的计算机和服务器之间上载和下载文件。操作系统对话框会提示用户选择要上载的文件或用于下载的位置。每个 FileReference 对象都引用用户磁盘上的一个文件并且具有一些属性,这些属性包含有关文件大小、类型、名称、创建日期、修改日期以及创建者的信息。

FileReference 实例的创建方法有两种:

对于上载和下载操作,SWF 文件只能访问自己的域(包括由跨域策略文件指定的任何域)内的文件。如果启动上载或下载的 SWF 与文件服务器不在同一个域中,则需要将策略文件放到文件服务器上。

注意

 

一次只能执行一个 browse()download() 操作,因为在任何时刻只能打开一个对话框。

处理文件上载的服务器脚本应收到包含下列元素的 HTTP POST 请求:

下面是一个 HTTP POST 请求范例:

POST /handler.asp HTTP/1.1
Accept: text/*
Content-Type: multipart/form-data;
boundary=----------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6
User-Agent: Shockwave Flash
Host: www.mydomain.com
Content-Length: 421
Connection: Keep-Alive
Cache-Control: no-cache

------------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6 
Content-Disposition: form-data; name="Filename"

sushi.jpg 
------------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6
Content-Disposition: form-data; name="Filedata"; filename="sushi.jpg"
Content-Type: application/octet-stream

Test File 
------------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6
Content-Disposition: form-data; name="Upload"

Submit Query
------------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6
(actual file data,,,)

下面的 HTTP POST 请求范例发送三个 POST 变量:api_sigapi_keyauth_token,并使用自定义上载数据字段名的值“photo”

POST /handler.asp HTTP/1.1
Accept: text/*
Content-Type: multipart/form-data;
boundary=----------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6
User-Agent: Shockwave Flash
Host: www.mydomain.com
Content-Length: 421
Connection: Keep-Alive
Cache-Control: no-cache

------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Filename"

sushi.jpg
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="api_sig"

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="api_key"

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="auth_token"

XXXXXXXXXXXXXXXXXXXXXXX
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="photo"; filename="sushi.jpg"
Content-Type: application/octet-stream

(actual file data,,,)
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Upload"

Submit Query
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--

将文件上载到服务器

要将文件上载到服务器,需要首先调用 browse() 方法,以允许用户选择一个或多个文件。接下来,当调用 FileReference.upload() 方法时,所选的文件将传输到服务器。如果用户使用 FileReferenceList.browse() 方法选择了多个文件,Flash Player 将创建一个称为 FileReferenceList.fileList 的所选文件数组。可随后使用 FileReference.upload() 方法分别上载每个文件。

注意

 

使用 FileReference.browse() 方法时,您只能上载单个文件。要允许用户上载多个文件,您必须使用 FileReferenceList.browse() 方法。

虽然开发人员可以通过使用 FileFilter 类并将文件过滤器实例数组传递给 browse() 方法来指定一个或多个自定义文件类型过滤器,但是默认情况下,系统文件选取器对话框允许用户从本地计算机选取任何文件类型:

var imageTypes:FileFilter = new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png");
var textTypes:FileFilter = new FileFilter("Text Files (*.txt, *.rtf)", "*.txt; *.rtf");
var allTypes:Array = new Array(imageTypes, textTypes);
var fileRef:FileReference = new FileReference();
fileRef.browse(allTypes);

用户在系统文件选取器中选择文件并单击“打开”按钮后,将调度 Event.SELECT 事件。如果使用 FileReference.browse() 方法选择要上载的文件,则需要用下面的代码将该文件发送到 Web 服务器:

var fileRef:FileReference = new FileReference();
fileRef.addEventListener(Event.SELECT, selectHandler);
fileRef.addEventListener(Event.COMPLETE, completeHandler);
try
{
    var success:Boolean = fileRef.browse();
}
catch (error:Error)
{
    trace("Unable to browse for files.");
}
function selectHandler(event:Event):void
{
    var request:URLRequest = new URLRequest("http://www.[yourdomain].com/fileUploadScript.cfm")
    try
    {
        fileRef.upload(request);
    }
    catch (error:Error)
    {
        trace("Unable to upload file.");
    }
}
function completeHandler(event:Event):void
{
    trace("uploaded");
}

提示

 

您可以使用 URLRequest.methodURLRequest.data 属性,通过 FileReference.upload() 方法将数据发送到服务器,以使用 POSTGET 方法发送变量。

当您尝试使用 FileReference.upload() 方法上载文件时,可能调度下列任何事件:

提示

 

Flash Player 不对需要身份验证的服务器提供完全支持。只有使用浏览器插件或 Microsoft ActiveX® 控件在浏览器中运行的 SWF 文件才可以提供一个对话框,来提示用户输入用户名和密码以进行身份验证,并且用户只有在通过身份验证后才能下载。对于使用插件或 ActiveX 控件进行的上载操作,或者使用独立或外部播放器进行的上载/下载操作,文件传输会失败。

如果在 ColdFusion 中创建服务器脚本以接受来自 Flash Player 的文件上载,可以使用类似如下的代码:

<cffile action="upload" filefield="Filedata" destination="#ExpandPath('./')#" nameconflict="OVERWRITE" />

此 ColdFusion 代码上载 Flash Player 发送的文件,并将其保存到 ColdFusion 模板所在的目录中以覆盖具有相同名称的任何文件。上面的代码显示接受文件上载所需的最低代码量;不应在生产环境中使用此脚本。理想情况下,应添加数据验证,以确保用户只上载接受的文件类型(例如图像),而不是上载可能危险的服务器端脚本。

下面的代码使用 PHP 说明文件上载,并且包含数据验证。该脚本将上载目录中的上载文件数限制为 10,确保文件小于 200 KB,并且只允许 JPEG、GIF 或 PNG 文件上载和保存到文件系统。

<?php
$MAXIMUM_FILESIZE = 1024 * 200; // 200KB
$MAXIMUM_FILE_COUNT = 10; // keep maximum 10 files on server
echo exif_imagetype($_FILES['Filedata']);
if ($_FILES['Filedata']['size'] <= $MAXIMUM_FILESIZE)
{
    move_uploaded_file($_FILES['Filedata']['tmp_name'], "./temporary/".$_FILES['Filedata']['name']);
    $type = exif_imagetype("./temporary/".$_FILES['Filedata']['name']);
    if ($type == 1 || $type == 2 || $type == 3)
    {
        rename("./temporary/".$_FILES['Filedata']['name'], "./images/".$_FILES['Filedata']['name']);
    }
    else
    {
        unlink("./temporary/".$_FILES['Filedata']['name']);
    }
}
$directory = opendir('./images/');
$files = array();
while ($file = readdir($directory))
{
    array_push($files, array('./images/'.$file, filectime('./images/'.$file)));
}
usort($files, sorter);
if (count($files) > $MAXIMUM_FILE_COUNT)
{
    $files_to_delete = array_splice($files, 0, count($files) - $MAXIMUM_FILE_COUNT);
    for ($i = 0; $i < count($files_to_delete); $i++)
    {
        unlink($files_to_delete[$i][0]);
    }
}
print_r($files);
closedir($directory);

function sorter($a, $b)
{
    if ($a[1] == $b[1])
    {
        return 0;
    }
    else
    {
        return ($a[1] < $b[1]) ? -1 : 1;
    }
}
?>

可以使用 POSTGET 请求方法将附加变量传递到上载脚本。要将附加 POST 变量发送到上载脚本,可以使用下面的代码:

var fileRef:FileReference = new FileReference();
fileRef.addEventListener(Event.SELECT, selectHandler);
fileRef.addEventListener(Event.COMPLETE, completeHandler);
fileRef.browse();
function selectHandler(event:Event):void
{
    var params:URLVariables = new URLVariables();
    params.date = new Date();
    params.ssid = "94103-1394-2345";
    var request:URLRequest = new URLRequest("http://www.yourdomain.com/FileReferenceUpload/fileupload.cfm");
    request.method = URLRequestMethod.POST;
    request.data = params;
    fileRef.upload(request, "Custom1");
}
function completeHandler(event:Event):void
{
    trace("uploaded");
}

上面的示例新建一个将传递到远程服务器端脚本的 URLVariables 对象。在早期版本的 ActionScript 中,可以通过在查询字符串中传递值来将变量传递到服务器上载脚本。在 ActionScript 3.0 中,可以使用 URLRequest 对象将变量传递到远程脚本,该对象允许您使用 POSTGET 方法传递数据;因此,可以更轻松和更清晰地传递较大数据集。为了指定是使用 GET 还是使用 POST 请求方法来传递变量,可以将 URLRequest.method 属性相应设置为 URLRequestMethod.GETURLRequestMethod.POST

在 ActionScript 3.0 中,还可以通过向 upload() 方法提供第二个参数来覆盖默认 Filedata 上载文件字段名称,如上面的示例所示(该示例使用 Custom1 替换默认值 Filedata)。

默认情况下,Flash Player 不尝试发送测试上载,虽然您可以通过将值 true 作为第三个参数传递给 upload() 方法来覆盖此行为。测试上载的目的是检查实际文件上载是否会成功,如果需要服务器身份,还会检查服务器身份验证是否会成功。

注意

 

目前,只在基于 Windows 的 Flash Player 上进行测试上载。

从服务器下载文件

您可以让用户使用 FileReference.download() 方法从服务器下载文件,该方法使用两个参数:requestdefaultFileName。第一个参数是 URLRequest 对象,该对象包含要下载的文件的 URL。第二个参数是可选的,它允许您指定出现在下载文件对话框中的默认文件名。如果省略第二个参数 defaultFileName,则使用指定 URL 中的文件名。

下面的代码从 SWF 文档所在的目录下载名为 index.xml 的文件:

var request:URLRequest = new URLRequest("index.xml");
var fileRef:FileReference = new FileReference();
fileRef.download(request);

要将默认名称设置为 currentnews.xml 而非 index.xml,请指定 defaultFileName 参数,如以下片断所示:

var request:URLRequest = new URLRequest("index.xml");
var fileToDownload:FileReference = new FileReference();
fileToDownload.download(request, "currentnews.xml");

如果服务器文件名不直观,或者文件名是由服务器生成的,则文件重命名可能非常有用。另外,在使用服务器端脚本下载文件(而不是直接下载文件)时,最好显式指定 defaultFileName 参数。例如,如果有基于传递给它的 URL 变量下载特定文件的服务器端脚本,则需要指定 defaultFileName 参数。否则,下载文件的默认名称即是服务器端脚本的名称。

可以使用 download() 方法将数据发送至服务器,方法是将参数追加到要分析的服务器脚本的 URL。下面的 ActionScript 3.0 片断基于传递给 ColdFusion 脚本的参数下载文档:

package
{
    import flash.display.Sprite;
    import flash.net.FileReference;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;

    public class DownloadFileExample extends Sprite
    {
        private var fileToDownload:FileReference;
        public function DownloadFileExample()
        {
            var request:URLRequest = new URLRequest();
            request.url = "http://www.[yourdomain].com/downloadfile.cfm";
            request.method = URLRequestMethod.GET;
            request.data = new URLVariables("id=2");
            fileToDownload = new FileReference();
            try
            {
                fileToDownload.download(request, "file2.txt");
            }
            catch (error:Error)
            {
                trace("Unable to download file.");
            }
        }
    }
}

下面的代码显示了 ColdFusion 脚本 download.cfm,该脚本根据 URL 变量的值从服务器下载两个文件之一:

<cfparam name="URL.id" default="1" />
<cfswitch expression="#URL.id#">
    <cfcase value="2">
        <cfcontent type="text/plain" file="#ExpandPath('two.txt')#" deletefile="No" />
    </cfcase>
    <cfdefaultcase>
        <cfcontent type="text/plain" file="#ExpandPath('one.txt')#" deletefile="No" />
    </cfdefaultcase>
</cfswitch>

FileReferenceList 类

使用 FileReferenceList 类,用户可以选择一个或多个要上载到服务器端脚本的文件。文件上载是由 FileReference.upload() 方法处理的,必须对用户选择的每个文件调用此方法。

下面的代码创建两个 FileFilter 对象(imageFiltertextFilter),并在一个数组中将它们传递到 FileReferenceList.browse() 方法。这导致操作系统文件对话框显示两个可能的文件类型过滤器。

var imageFilter:FileFilter = new FileFilter("Image Files (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg; *.jpeg; *.gif; *.png");
var textFilter:FileFilter = new FileFilter("Text Files (*.txt, *.rtf)", "*.txt; *.rtf");
var fileRefList:FileReferenceList = new FileReferenceList();
try
{
    var success:Boolean = fileRefList.browse(new Array(imageFilter, textFilter));
}
catch (error:Error) 
{
    trace("Unable to browse for files.");
}

允许用户使用 FileReferenceList 类选择并上载一个或多个文件与使用 FileReference.browse() 选择文件是相同的,但 FileReferenceList 允许选择多个文件。上载多个文件时,要求您使用 FileReference.upload() 上载每个所选的文件,如以下代码所示:

var fileRefList:FileReferenceList = new FileReferenceList();
fileRefList.addEventListener(Event.SELECT, selectHandler);
fileRefList.browse();

function selectHandler(event:Event):void
{
    var request:URLRequest = new URLRequest("http://www.[yourdomain].com/fileUploadScript.cfm");
    var file:FileReference;
    var files:FileReferenceList = FileReferenceList(event.target);
    var selectedFileArray:Array = files.fileList;
    for (var i:uint = 0; i < selectedFileArray.length; i++)
    {
        file = FileReference(selectedFileArray[i]);
        file.addEventListener(Event.COMPLETE, completeHandler);
        try
        {
            file.upload(request);
        }
        catch (error:Error)
        {
            trace("Unable to upload files.");
        }
    }
}
function completeHandler(event:Event):void
{
    trace("uploaded");
}

由于将 Event.COMPLETE 事件添加到数组中每个单独的 FileReference 对象中,因此,Flash Player 在每个单独文件完成上载时将调用 completeHandler() 方法。


Flash CS3

 

评论添加到页面后给我发送电子邮件 | 评论报告

当前页: http://livedocs.adobe.com/flash/9.0_cn/main/00000320.html