随笔-254  评论-3298  文章-48  trackbacks-74

Flex与.NET互操作(五):使用FileReference+HttpHandler实现文件上传/下载

     在Flex的应用开发中,同ASP.NET,JSP,PHP等应用一样,都会有上传/下载文件的应用需求,Flex的SDK也为我们提供了专门的类FileRefUdderence实现文件上传/下载 。Flex只是作为一个客户端,要实现上传或下载必须得为其提供一个服务端来接受上传或下载的请求,本文以ASP.NET中的HttpHandler作为文件上传的服务端来完成上传功能。

     OK,我们从Flex客户端开始,看看客户端是通过什么方式想服务端发起请求。Flex客户端要完成文件上传下载都是通过FileRefUdderence来实现,首先得定义一个该类型对象实例:

1 [Bindable]
2 private var stateText:String = "请选择一个文件上传";
3 //通过调用file对象的方法来完成上传和下载功能
4 private var file:FileReference = new FileReference();

 

     上传文件通常涉及到的有选择文件、上传文件以及上传完成这些最基本的处理过程。OK,下面我们就以这三个过程为例来看看Flex是怎么来完成文件的上传功能。首先为这三个功能点分别添加监听事件处理函数,在程序加载时调用:

1 internal function initApp():void
2 {
3     file.addEventListener(Event.SELECT,onSelected);
4     file.addEventListener(Event.COMPLETE,onCompleted);
5     file.addEventListener(ProgressEvent.PROGRESS,onProgress);
6 }

 

     另外我们也可以不用上面这中定义一个函数在程序加载时调用进行初始化操作,应用程序(mxml)的初始化操作又creationComplete方法完成,另外还有一个比它先执行的方法createChildren(),我们可以直接在mxml下重写该方法来实现应用程序的初始化,如下:

1 /**
2  * createChildren 比 creationComplete 事件更早发生
3  * */
4 protected override function createChildren():void
5 {
6     file.addEventListener(Event.SELECT,onSelected);
7     file.addEventListener(Event.COMPLETE,onCompleted);
8     file.addEventListener(ProgressEvent.PROGRESS,onProgress);
9 }

 

     这三个事件处理函数的详细定义如下(其中的stateText为String的变量,用于显示文件上传状态提示):

 1 internal function onSelected(evt:Event):void
 2 {
 3     stateText = "选择了文件" + file.name;
 4 }
 5 
 6 internal function onCompleted(evt:Event):void
 7 {
 8     stateText = "上传完毕!";
 9 }
10 
11 internal function onProgress(evt:ProgressEvent):void
12 {
13     stateText = "已上传 " + Math.round(100 * evt.bytesLoaded / evt.bytesTotal) + "%";
14 }

 

     到这里客户端就只差一步了,那就是完成发起上传请求的方法,实际上就是通过URLRequest对象创建一个与服务端的连接,然后直接调用FielReference类的upload()方法就可完成该功能,详细如下代码定义:

 1 /**
 2  * 调用FileReference的实例方法upload()实现文件上传
 3  * */
 4 internal function onUpLoad():void
 5 {
 6     if(file.size > 0)
 7     {
 8         stateText = "正在上传文件:" + file.name;
 9     }
10     var request:URLRequest = new URLRequest();
11     request.url="http://localhost/Web/UpLoadHandler.ashx";
12     file.upload(request);
13 }

 

     写好了upload方法,现在就是调用他了,通过按扭的click事件直接调用就可以,另外调用file.browse()方法则实现选择文件的功能,如下mxml代码描述:

1 <mx:TextInput x="10" y="57" id="txtFile" text="{stateText}" width="229"/>
2 <mx:Button x="247" y="57" label="选择" fontWeight="normal" click="{file.browse()}"/>
3 <mx:Button x="29" y="111" label="上传文件" width="111" fontWeight="normal" click="onUpLoad()"/>

 

     如上便完成了上传文件的Flex客户端开发,通过file.upload()方法,将把选择的文件通过二进制的形式发送到指定的服务端,并自动传递一个叫“fileName”的参数,服务端通过fileName便可以接收到客户端请求上传的文件。最后我们来看看服务端的UpLoadHandler.ashx的详细定义:

 1 public class UpLoadHandler : IHttpHandler
 2 {
 3     //文件上传目录
 4     private string uploadFolder = "UpLoad";
 5 
 6     public void ProcessRequest(HttpContext context)
 7     {
 8         context.Response.ContentType = "text/plain";
 9 
10         HttpFileCollection files = context.Request.Files;
11         if (files.Count > 0)
12         {
13             string path = context.Server.MapPath(uploadFolder);
14             HttpPostedFile file = files[0];
15 
16             if (file != null && file.ContentLength > 0)
17             {
18                 string savePath = path + "/" + context.Request.Form["fileName"];
19                 file.SaveAs(savePath);
20             }
21         }
22         else
23         {
24             context.Response.Write("参数错误");
25             context.Response.End();
26         }
27     }
28 
29     public bool IsReusable
30     {
31         get
32         {
33             return false;
34         }
35     }
36 }

 

     如上一系列的步骤便可完成上传文件的功能,下面便是上传文件示例程序运行截图:     
     

 

     实现了文件上传下面来看看怎么实现文件下载, 以上面上传示例中上传的mp3为例,下面我们来看看怎么从服务器(http://localhost/Web/UpLoad/做你的爱人.mp3)上完成文件(做你的爱人.mp3)的下载。

     要实现文件下载对服务器端只要保证被下载文件存在就OK,同上传文件一样需要实例化一个FielReference对象的实例,并为其添加相应的事件处理函数:

1 private var fileDown:FileReference = new FileReference();

 

 1 /**
 2  * createChildren 比 creationComplete 事件更早发生
 3  * */
 4 protected override function createChildren():void
 5 {
 6     super.createChildren();
 7     file.addEventListener(Event.SELECT,onSelected);
 8     file.addEventListener(Event.COMPLETE,onCompleted);
 9     file.addEventListener(ProgressEvent.PROGRESS,onProgress);
10     //实现文件下载
11     fileDown.addEventListener(Event.COMPLETE,onDownCompleted);
12     fileDown.addEventListener(ProgressEvent.PROGRESS,onDownProgress);
13 }

 

     如上为实现下载文件的实例fileDown注册了成功下载文件后事件处理函数和下载过程处理函数,下面是两个方法的详细定义:

 1 internal function onDownCompleted(evt:Event):void
 2 {
 3     var fileRef:FileReference = evt.currentTarget as FileReference;
 4     resultLabel.text = "文件名:" + fileRef.name + "下载完毕!";
 5 }
 6 
 7 internal function onDownProgress(evt:ProgressEvent):void
 8 {
 9     downState.text = "已下载: " + Math.round(100 * evt.bytesLoaded / evt.bytesTotal) + "%";
10 }

 

     完成了对象事件的开发,最后便上惩罚下载请求了,直接调用FileReference类所提供的download()方法既可:

1 /**
2  * 调用FileReference类的实例方法download()实现文件下载
3  * */
4 internal function onDownLoad():void
5 {
6     var request:URLRequest = new URLRequest();
7     request.url="http://localhost:1146/UpLoad/做你的爱人.mp3";
8     fileDown.download(request);
9 }

 

     程序执行到download()方法的时候会自动弹出选择保存文件对话框,根据实际情况选择好保存路径就OK。下面是实现上传和下载的完整代码:

实现上传和下载的完整代码

 

     程序运行截图:

      

 

版权说明

  本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

posted on 2009-01-18 01:38 Bēniaǒ 阅读(7889) 评论(18) 编辑 收藏

评论:
#1楼 2009-01-18 12:57 | koumi      
看的出来,很少有人关注FLEX,
 回复 引用 查看   
#2楼 2009-01-18 12:58 | koumi      
楼主,以后多向你请教这方面的知识哟!!
 回复 引用 查看   
#3楼[楼主] 2009-01-18 14:05 | Bēniaǒ      
@koumi
是啊,过段时间应该关注的人就比较多了。

 回复 引用 查看   
#4楼 2009-01-18 14:39 | Michael-Chen      
辛苦咯!!!~!
 回复 引用 查看   
#5楼[楼主] 2009-01-18 23:47 | Bēniaǒ      

 回复 引用 查看   
#6楼 2009-01-19 08:29 | 至于臻善[未注册用户]
支持大附件么?
 回复 引用   
#7楼[楼主] 2009-01-19 09:18 | Bēniaǒ      
@至于臻善
使用FileReference上传不支持大附件,官方说法可以支持100M的文件,但是我没试过,测试上传50M的文件到本地IIS服务器报了15秒超时异常,修改下设置应该是没问题的。

 回复 引用 查看   
#8楼 2009-01-19 09:56 | 盖天[未注册用户]
学习...
 回复 引用   
#9楼 2009-02-14 16:59 | 导弹888[未注册用户]
请教 ,这种上传方式下:
如果想同时把图片的URL,title等 信息存入数据库,应该怎么做?
另外,如果服务器端有重名文件怎么判断 ,并把重名的消息 返回给flex端?

 回复 引用   
#10楼[楼主] 2009-02-15 04:11 | Bēniaǒ      
@盖天
大家一起学习。

 回复 引用 查看   
#11楼[楼主] 2009-02-15 04:16 | Bēniaǒ      
@导弹888
这种方式上传实质上和asp.net的form提交没多大的区别,你可以通过HttpFileCollection获取相关的参数。详细你查看AS的API就明白了。

 回复 引用 查看   
#12楼 2009-07-17 21:46 | 学习as3[未注册用户]
file.name 只能获得文件的名字
那盘符和文件夹如何获得呢?

 回复 引用   
#13楼 2009-08-20 13:26 | hehehe12[未注册用户]
根本解决不了大文件上传的问题。
flex仅仅是客户端,无论它支持多大文件的上传都是没有意义的。
还是需要asp.net去做处理。

 回复 引用   
#14楼 2011-02-17 23:38 | 大侠酷裤马路      
试验有成功,谢谢benniao 继续往下
 回复 引用 查看   
#15楼[楼主] 2011-02-18 12:56 | Bēniaǒ      
@大侠酷裤马路
引用大侠酷裤马路:试验有成功,谢谢benniao 继续往下

多多支持。

 回复 引用 查看   
#16楼 2011-02-24 16:33 | huangzy      
请问如果要上传2G+的文件,该怎么办???
 回复 引用 查看   
#17楼 2011-06-23 16:50 | 羊圈里最帅的羊      
楼主,你的下载代码中带有中文名称的文件根本就下载不了,要作如下修改:
internal function onDownLoad():void
{
var url:String=encodeURI("http://localhost:3035/UPLOAD/中文歌曲名.mp3");
var request:URLRequest = new URLRequest(url);
fileDown.download(request,"中文歌曲名.mp3");
}

 回复 引用 查看   
#18楼 2011-08-28 11:57 | 国家主席      
flex入门的好资料
 回复 引用 查看   
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1377668 2R0VgDzQ8CU=
微软最有价值专家(MVP)

微软技术社区精英(CNTAC)

2010年IT博客大赛50强

微软最有影响力开发者(GDI)


Bing Maps开发一群:75662563
微软技术群-重庆站:97035589
RIA技术联盟QQ群:26917590
昵称:Bēniaǒ
园龄:4年6个月
荣誉:推荐博客
粉丝:408
关注:26

随笔分类(285)

文章分类(14)

积分与排名

  • 积分 - 760874
  • 排名 - 60

最新评论