一般而言,用户不希望web浏览器中运行的应用程序访问电脑硬盘里的文件。然而,随着基于浏览器(browser-based)的富因特网应用程序的增多,一些应用程序迫切需要访问用户所选择的文件,或者将文件保存到用户所选择的位置。支持FileReference类的Adobe Flash Player版本允许ActionScript应用程序将用户所选择的文件上传到服务器,或者从服务器下载文件到用户所选择的位置。然而,在Flash Player 10之前的版本中,除非您先将数据传送到服务器,否则无法在应用程序中访问文件内容,也无法把应用程序的数据保存到本地的文件。
从Flash Player 10开始,FileReference类附加地能够打开用户选择的本地文件以及保存数据到用户选择的位置,而无需与服务器之间的文件往返。 对于能够加载本地文件以供使用,或者能够保存数据到本地文件的富因特网应用程序来说,这将大大地简化开发的过程。 为了安全起见,在Flash Player 中运行的ActionScript代码不能直接地访问本地文件系统来打开或保存文件。 应用在这一Quick Start(快速入门)里介绍的技术,这些代码通常会引出一个对话框,提示用户选择一个文件用于打开或者指定一个位置来保存文件。 另外,尽管用户已经选择了一个要打开文件,但无法确定文件所在的本地路径。 只有文件的名字是可用的。
图1所示的Crop Rectangle示例程序展示了如何从用户(在自己电脑上)选择的文件中加载数据,如何在应用程序中使用那个文件,以及如何在用户电脑上创建和保存数据到一个文件。 该应用程序的工作流程如下:
示例应用程序包含以下文件:
为了测试这个程序,您可以在浏览器中尝试使用该程序(见图1),或者通过编译源代码来运行这个示例。
注意:这是一个出于指导目的而提供的示例程序。
Crop Rectangle示例使用FileReference对象来打开和保存用户电脑上的文件。 它使用Loader 类和Bitmap类在屏幕上显示图像。 它使用BitmapData类和ByteArray类来裁剪出图像的一部分,并将它编码成数据,使其可以保存到用户电脑中。
注意:示例中也用到了其它的类,主要是显示对象和用户界面的组件,这些类定义了应用程序的用户界面。这里的Quick Start不会对用户界面的所有功能或程序的其他部分进行描述。
以下是程序打开、处理和保存文件的步骤概述:
FileReference.browse()
方法提示用户选择文件。当选择完毕,FileReference对象会分派一个选择事件。FileReference.load()
把所选的文件加载到一个变量里。当加载完毕,它会分派一个完成事件。文件数据在FileReference对象的数据属性中可用。Loader.loadBytes()
方法把来自FileReference.data属性的图像文件数据转化为一个Bitmap实例。当转化完毕,Loader
的contentLoaderInfo 属性中的LoaderInfo对象会分派一个完成事件。BitmapData.draw()
方法捕捉,并保存在BitmapData对象中。FileReference.save()
方法的调用会提示用户选择一个保存位置。需保存的数据以参数的形式传送到save()
方法。当save()
操作完毕,FileReference对象会分派一个完成事件。如果操作过程存在错误,它则会分派一个ioError事件。在这篇Quick Start余下部分中,会对这些步骤作出更详细的解释。
Crop
Rectangle应用程序使用FileReference对象来表示用户所选择和加载的文件。在本示例中,这些代码位于Crop类之中。加载文件的过程包括两个步骤:使用FileReference.browse()
方法提示用户选择一个文件,以及使用FileReference.open()
方法把文件数据加载到Flash
Player。每个任务都会使用事件来通知您该任务是否完成。因此,在源码中,这一过程分开在好几个方法中。
第一个是startLoadingFile()
方法。在程序的第一个画面中,当用户点击按钮时,便会调用这个方法。然后,它提示用户选择打开一个文件。以下是startLoadingFile()
方法的源码:
private
var _loadFile:FileReference; private function startLoadingFile():void {
_loadFile = new FileReference(); _loadFile.addEventListener(Event.SELECT,
selectHandler); var fileFilter:FileFilter = new FileFilter("Images: (*.jpeg,
*.jpg, *.gif, *.png)", "*.jpeg; *.jpg; *.gif; *.png");
_loadFile.browse([fileFilter]); }
用于选择和打开文件的FileReference对象是一个命名为_loadFile
的私有实例变量(private instance
variable)。因为_loadFile
会在Crop类的各个方法中使用,所以它必须在整个类中都可用,于是使用了这一个实例变量。
startLoadingFile()
方法处理了以下事情:
selectHandler()
的方法注册为选择事件的监听器(listener)。在用户被提示选择一个文件,并已经选择完毕之后,这个选择事件被分派(取消对话框的话不会分派这个事件)。browse()
方法。该browse()
方法会令Flash
Player显示一个允许用户选择打开一个文件的对话框。当用户选择了一个文件并在对话框中点击Open按钮之后,FileReference对象会分派出选择事件,并调用selectHandler()
方法。selectHandler()
方法将执行下一个步骤,file-loading(文件加载)过程:把所选的文件加载到Flash
Player的内存:
private
function selectHandler(event:Event):void {
_loadFile.removeEventListener(Event.SELECT, selectHandler); // ... display the
progress bar for the loading operation ...
_loadFile.addEventListener(Event.COMPLETE, loadCompleteHandler);
_loadFile.load(); }
loadCompleteHandler()
的方法注册为_loadFile对象的完成事件的监听器(listener)。当FileReference完成把文件数据从硬盘读取到内存之后,它会分派一个完成事件。load()
方法。load()
方法会启动把文件读取到代码能够访问的内存之中的过程。当加载文件的操作完成时,_loadFile
会派遣完成事件,并调用命名为loadCompleteHandler()
的方法。该方法的功能将在下一节介绍。
当您使用FileReference对象的load()
方法从文件加载数据的时候,文件的内容会被加载到FileReference对象的数据属性(data
property)。FileReference.data
属性是一个包含文件原始二进制数据的ByteArray(字节数组)对象。您使用
ByteArray类的方法来读取文件的内容,并在您的程序中使用它们。例如,如果文件来自一个文字处理的应用程序,您也许希望把文本提取出来并显示到屏幕上。您甚至可以创建自定义的文件格式,并且在您的程序里加载和保存这种格式的文件。
对于Crop Rectangle应用程序,加载的文件包含图像数据,格式为JPEG、 PNG或
GIF。在这样的程序中,我们不想读文件数据中某些部分的内容;我们只想使用那些能把图像显示到屏幕的数据。为了把原始的图像数据显示到屏幕上,您要使用
Loader类的loadBytes()
方法。您把数据(以ByteArray(字节数组)格式)传递到Loader对象,然后Loader对象会使用这些数据来创建一个ActionScript显示对象。它所创建的显示对象的类型是基于传递给它的数据类型。在这种情况下,由于应用程序只允许用户选择图像文件,所以Loader从这些图像文件数据创建一个Bitmap
object(位图对象)。结果与您使用Loader从一个web服务器加载图像文件完全一样。与这份Quick
Start中描述过的其它过程一样,Loader对象的loadBytes()
方法无须即时地创建一个临时显示对象。作为取代的方法,当Loader完成把数据转化到显示对象的时候,与Loader对象对应的LoaderInfo对象会分派一个完成事件。在那时候,您就能知道显示对象可以被添加到显示列表了。
正如以上章节所描述的那样,当leReference对象完成把文件从硬盘加载到内存的时候,它会分派完成事件。在Crop
Rectangle应用程序中,名为_loadFile
的FileReference对象会加载用户所选择的图像文件。当加载完成时,loadCompleteHandler()
方法会被调用,因为它被注册为完成事件的监听器。
然后loadCompleteHandler()
方法开始把图像显示到屏幕这一过程:
private
function loadCompleteHandler(event:Event):void {
_loadFile.removeEventListener(Event.COMPLETE, loadCompleteHandler); var
loader:Loader = new Loader(); // ... display the progress bar for converting the
image data to a display object ...
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadBytesHandler);
loader.loadBytes(_loadFile.data); }
loadCompleteHandler()
处理以下的事情:
_loadFile
对象的完成事件的监听器(listener)。loadBytes()
方法的进度(没有展示出来)。loadBytesHandler()
方法注册为当Loader完成创建显示对象的时候(特别地,当Loader对象的contentLoaderInfo属性的LoaderInfo对象分派出一个完成事件的时候)被调用。loadBytes()
方法,传递包含已加载文件内容的ByteArray(_loadFile.data属性)给它。当Loader对象的loadBytes()
操作完成的时候,contentLoaderInfo属性的LoaderInfo对象会分派一个完成事件。在这个示例中,它会调用loadBytesHandler()
方法。下面是loadBytesHandler()
方法的源码:
private
function loadBytesHandler(event:Event):void { var loaderInfo:LoaderInfo =
(event.target as LoaderInfo); loaderInfo.removeEventListener(Event.COMPLETE,
loadBytesHandler); showImage(loaderInfo.content); }
loadBytesHandler()
方法处理两件事情。首先,它移除自身作为LoaderInfo对象的完成事件的监听器。接着,它调用一个命名为showImage()
的方法,把新创建的(newly-created)显示对象(loaderInfo.content
属性)传递给它。
showImage()
方法太大了,而不适合包含在这里,但它的工作直截了当地就是显示对象的操作任务。它创建一个命名为_imageContainer
的Sprite来作为图像的容器。它装载了从所加载图像文件创建的显示对象,并通过调用_imageContainer
对象的addChild()
方法把它添加到显示列表(display
list)。如果有必要,它还会调整图片的大小,使图片适应于程序的可视区域,并且把它放置在屏幕中央。
一旦用户选定了图像保留的部分和图像的输出格式(JPEG 或 PNG),然后就可以点击"Save image"按钮。 在那个时候,应用程序需要为保存剪裁图像到用户电脑做几件准备工作:
这些步骤与随后章节中描述的其它步骤一样,会出现在Crop类的cropAndSave()
方法中。当用户点击Save
image按钮的时候,这个方法会被调用。
首先,代码中用来获取图像选定区域对应矩形坐标的部分,使用了如下这一行代码:
var
cropRect:Rectangle = _cropStateView.getCropRect();
命名为cropRectangle的
Rectangle对象包含了选定图像区域的坐标。Rectangle是通过调用_cropStateView
对象的getCropRect()
方法来获取的。_cropStateView
对象是CropStateView类的一个实例。这个类定义了应用程序在这个时候的用户界面代码。这篇Quick
Start没有描述如何计算Rectangle对象的细节;要充分注意的是,现在cropRect对象是可用的,并且它包含有选定区域的坐标。
下一步,创建一个命名为imageData的BitmapData对象,使用的代码如下:
var
imageData:BitmapData = new BitmapData(cropRect.width,
cropRect.height);
命名为imageData的BitmapData对象将会包含剪裁图像的像素数据。创建的BitmapData对象中的宽度和高度与 cropRect的Rectangle对象中的宽度和高度相匹配。因此,当像素复制到imageData的时候,只有选定矩形尺寸区域的数据被复制。
下一行代码将创建一个命名为shiftOrigin的Matrix对象。这个对象定义了原图的位置,它会成为复制到名为imageData的BitmapData对象的区域的左上角。用以下代码创建这个对象:
var
shiftOrigin:Matrix = new Matrix(); shiftOrigin.translate(-cropRect.x,
-cropRect.y);
Matrix对象的translate()
方法引起用于像素复制操作的源图像转化为指定数目的像素。(屏幕上真正的显示对象是不会移动的——只是显示对象概念上的位置相对于像素数据快照的开始坐标。)请注意,传递到translate()
方法的参数是负数。概念上,您可以把BitmapData对象想象为一个照相机,它拍下像素的快照。然而,因为照相机的位置是固定的,所以被照的图像需要移动以便捕捉指定的裁剪区域。图像必须根据Rectangle的x坐标和y坐标来上移和左移相同的数量,以便被选定的矩形的左上角与概念上的"照相机"左上角对齐。因此,translate()
的参数是负数。
接着,通过调用BitmapData对象的draw()
方法,把Stage上的图像像素复制到它里面:
imageData.draw(_imageContainer,
shiftOrigin);
draw()
方法把显示对象的像素复制到BitmapData对象。传递给draw()
方法的参数如下:
_imageContainer
:装载着Stage上的已加载图像的Sprite(源显示对象)。shiftOrigin
:如上所述,Matrix对象指定了像素快照的开始位置。名为imageData的BitmapData对象中有选定矩形的像素数据快照,那些图像数据可以转化成适当的图像格式。在Crop Rectangle应用程序示例中,有两种可选的输出格式:JPEG 和 PNG。以下代码确定了对应于这两种格式的按钮之中的哪一个会被选择。然后,这些代码会使用合适的编码器来创建一个包含有转化为指定格式图像数据的 ByteArray(encodedImage(编码图像))。
var
encodedImage:ByteArray; if (_cropStateView.outputFormat == CropStateView.JPEG) {
var jpgEncoder:JPGEncoder = new JPGEncoder(85); encodedImage =
jpgEncoder.encode(imageData); } else { encodedImage =
PNGEncoder.encode(imageData); }
"_cropStateView变量是CropStateView类的一个实例,包含了这部分程序的用户界面代码。它有一个名为outputFormat
的属性,该属性值指示了所选择的输出格式选项按钮。CropStateView类也定义了两个常量,CropStateView.JPEG
和CropStateView.PNG
,代表outputFormat
属性可能出现的两个值。
JPGEncoder类和PNGEncoder类可以把BitmapData对象分别转化为包含这两种格式图像数据的ByteArray对象。这些类来自开源的as3corelib项目,它们是在New BSD许可证下发布的。
前面的章节描述了如何将用户选定的矩形剪裁区域捕捉到BitmapData对象之中,并把它转化成名为encodedImage的ByteArray对象。下一个任务就是要把ByteArray数据以文件的形式保存到用户电脑里。与打开文件一样,保存文件也是一个多步骤的操作,通过事件来指示操作步骤是否完成。我们继续来讨论cropAndSave()
方法,这些代码会在保存对话框中生成一个建议的文件名:
var
fileNameRegExp:RegExp = /^(?P<fileName>.*)\..*$/; var
outputFileName:String = fileNameRegExp.exec(_loadFile.name).fileName + "_crop";
if (_cropStateView.outputFormat == CropStateView.JPEG) { outputFileName +=
".jpg"; } else { outputFileName += ".png"; }
在这里,我们希望默认的文件名是源文件名(不含扩展名),加上文字"_crop",再加上与所选文件格式一致的文件扩展名。这些代码使用规则表达式对象(fileNameRegExp)来获取不含扩展名的源文件名称。这个规则表达式对象的exec()
方法会在任何传递进来的参数上执行规则表达式模型。在这些代码中,_loadFile.name属性会被传递到exec()
方法。请记住,_loadFile
是一个FileReference
对象,对应于用户在开始时所打开的源图像文件。FileReference对象的name
属性包含了所选文件的全名,包括有文件扩展名。因为规则表达式模式使用了一个名为fileName的named
capturing
group(命名捕捉组),所以当exec()
方法被调用的时候,返回的结果中有一个名为fileName的属性,包含了不带扩展名的文件名。字符串
"_crop"会连接到返回结果的末尾,然后整个文件名会保存到outputFileName变量之中。
剩下的工作就是要添加与用户选定的输出文件类型相适应的文件扩展名。条件语句会检查选择了哪种输出格式,然后添加适当的扩展名(".jpg"或 ".png")到outputFileName。
接着,代码开始进行保存JPEG或PNG图像数据到文件的操作,如下所示:
var
saveFile:FileReference = new FileReference();
saveFile.addEventListener(Event.COMPLETE, saveCompleteHandler);
saveFile.addEventListener(IOErrorEvent.IO_ERROR, saveIOErrorHandler);
saveFile.save(encodedImage, outputFileName);
列出的代码处理以下三件事情:
saveCompleteHandler
是完成事件的一个监听器,当用户选择了保存目标,并且Flash
Player完成把文件写进硬盘的操作之后,这个完成事件会被分派。saveIOErrorHandler
方法是ioError事件的一个监听器, 当Flash
Player在所选位置保存文件发生错误时,这个事件会被分派。save
方法。这个save
方法会打开一个对话框来提示用户选择保存文件的位置。它接受两个参数。对象传递的第一个参数是encodedImage——这个ByteArray包含有即将保存到文件的数据(在这个例子,是JPEG
或
PNG图像数据)。第二个传递的参数是outputFileName变量。这个值会在保存对话框中作为建议文件名。虽然用户可以修改文件名,但这是指定一个推荐文件扩展名的唯一方法,因此用它来提供默认名称是有好处的。假设用户没有取消保存操作,名为saveFile的FileReference对象便开始把数据保存到硬盘上。在这个示例种,因为传递了一个ByteArray到save
方法,所以这个ByteArray的内容会被直接保存到硬盘上。如果传递到save
方法的是一个不同类型的对象,那么写进文件的数据就会是不同的格式。例如,包含有String(字符串)或XML值的String(字符串)或XML对象作为一个文本文件写入。所有文件格式选项的列表,请参考ActionScript
3.0 Reference for the Adobe Flash Platform中的FileReference.save
所列。
当文件被成功保存之后,FileReference对象会分派一个完成事件。在之前的代码中,saveCompleteHandler
方法被注册为这个事件的监听器,所以当文件成功保存时,FileReference对象会调用这个方法。saveCompleteHandler
方法的代码没有包含在这篇Quick
Start之中。它仅仅执行了clean-up(清除)操作(移除事件的监听器),并引起用户界面显示出文件已经保存的消息。
如果在FileReference对象尝试保存文件的时候发生错误,它会分派出一个ioError
事件。在那种情况下,FileReference对象会调用saveIOErrorHandler
方法。这个方法仅仅会清理事件的监听器,并显示错误消息。
文章来源: http://www.adobe.com/cn/devnet/flash/quickstart/filereference_class_as3.html
详细解释 使用FileReference类加载和保存本地文件,码迷,mamicode.com
详细解释 使用FileReference类加载和保存本地文件
原文地址:http://www.cnblogs.com/xxjudfc/p/3702960.html