Flash CS3 文档 |
|||
| ActionScript 3.0 编程 > 网络与通信 > 处理文件上载和下载 | |||
可通过使用 FileReference 类,在客户端和服务器之间添加上载和下载文件的功能。将通过一个对话框(例如,Windows 操作系统中的“打开”对话框)提示用户选择要上载的文件或用于下载的位置。
使用 ActionScript 创建的每个 FileReference 对象都引用用户硬盘上的一个文件。该对象的属性包含有关文件大小、类型、名称、创建日期和修改日期的信息。
|
注意 |
|
仅 Mac OS 支持 |
可以通过两种方式创建 FileReference 类的实例。可以使用 new 运算符,如以下代码所示:
import flash.net.FileReference; var myFileReference:FileReference = new FileReference();
或者,可以调用 FileReferenceList.browse() 方法,该方法在用户的系统中打开一个对话框,提示用户选择一个或多个要上载的文件,如果用户成功选择了一个或多个文件,将创建一个由 FileReference 对象组成的数组。每个 FileReference 对象表示用户在对话框中选择的一个文件。FileReference 对象在 FileReference 属性(例如 name、size 或 modificationDate)中不包含任何数据,直到发生下列任一情况:
FileReference.browse() 方法或 FileReferenceList.browse() 方法,并且用户已经从文件选取器中选择了文件。FileReference.download() 方法,并且用户已经从文件选取器中选择了文件。|
注意 |
|
当执行下载时,在下载完成前只填充 |
在执行对 FileReference.browse()、FileReferenceList.browse() 或 FileReference.download() 方法的调用时,大多数播放器将继续 SWF 文件播放。
使用 FileReference 类可以在用户的计算机和服务器之间上载和下载文件。操作系统对话框会提示用户选择要上载的文件或用于下载的位置。每个 FileReference 对象都引用用户磁盘上的一个文件并且具有一些属性,这些属性包含有关文件大小、类型、名称、创建日期、修改日期以及创建者的信息。
FileReference 实例的创建方法有两种:
new 运算符和 FileReference 构造函数,如下所示: var myFileReference:FileReference = new FileReference();
FileReferenceList.browse(),从而创建 FileReference 对象数组。对于上载和下载操作,SWF 文件只能访问自己的域(包括由跨域策略文件指定的任何域)内的文件。如果启动上载或下载的 SWF 与文件服务器不在同一个域中,则需要将策略文件放到文件服务器上。
|
注意 |
|
一次只能执行一个 |
处理文件上载的服务器脚本应收到包含下列元素的 HTTP POST 请求:
Content-Type,其值为 multipart/form-data。Content-Disposition,其 name 属性设置为“Filedata”,filename 属性设置为原始文件的名称。您可以通过在 FileReference.upload() 方法中传递 uploadDataFieldName 参数的值来指定自定义 name 属性。下面是一个 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_sig、api_key 和 auth_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() 方法分别上载每个文件。
|
注意 |
|
使用 |
虽然开发人员可以通过使用 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");
}
|
提示 |
|
您可以使用 |
当您尝试使用 FileReference.upload() 方法上载文件时,可能调度下列任何事件:
Event.OPEN:上载操作开始时调度。ProgressEvent.PROGRESS:文件上载操作期间定期调度。Event.COMPLETE:文件上载操作成功完成时调度。SecurityErrorEvent.SECURITY_ERROR:由于安全侵犯导致上载失败时调度。HTTPStatusEvent.HTTP_STATUS:由于 HTTP 错误导致上载失败时调度。IOErrorEvent.IO_ERROR:由于下列任何原因导致上载失败时调度: url 参数包含无效协议。FileReference.upload() 方法必须使用 HTTP 或 HTTPS。|
提示 |
|
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;
}
}
?>
可以使用 POST 或 GET 请求方法将附加变量传递到上载脚本。要将附加 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 对象将变量传递到远程脚本,该对象允许您使用 POST 或 GET 方法传递数据;因此,可以更轻松和更清晰地传递较大数据集。为了指定是使用 GET 还是使用 POST 请求方法来传递变量,可以将 URLRequest.method 属性相应设置为 URLRequestMethod.GET 或 URLRequestMethod.POST。
在 ActionScript 3.0 中,还可以通过向 upload() 方法提供第二个参数来覆盖默认 Filedata 上载文件字段名称,如上面的示例所示(该示例使用 Custom1 替换默认值 Filedata)。
默认情况下,Flash Player 不尝试发送测试上载,虽然您可以通过将值 true 作为第三个参数传递给 upload() 方法来覆盖此行为。测试上载的目的是检查实际文件上载是否会成功,如果需要服务器身份,还会检查服务器身份验证是否会成功。
|
注意 |
|
目前,只在基于 Windows 的 Flash Player 上进行测试上载。 |
您可以让用户使用 FileReference.download() 方法从服务器下载文件,该方法使用两个参数:request 和 defaultFileName。第一个参数是 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 类,用户可以选择一个或多个要上载到服务器端脚本的文件。文件上载是由 FileReference.upload() 方法处理的,必须对用户选择的每个文件调用此方法。
下面的代码创建两个 FileFilter 对象(imageFilter 和 textFilter),并在一个数组中将它们传递到 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