一、实现原理。
在某些场合,我们需要使用Flash进行“文件上传”,原因是Flash 能制作出表现力丰富的UI界面。

(自负又孤陋寡闻的我在这里做一个补充:Flash使用flash.net包中的FileReference是可以发送文件数据到一个asp,asp.net或php页的,可以看浪子的[Flash FileUpload]用flash.net.FileReference实现ASP.NET无刷新文件上传,codeproject有这样的示例:Multiple File Upload With Progress Bar Using Flash and ASP.NET,Flash8的帮助中有FileReference的详细说明及示例。)

所以本文是用另一个方法来实现Flash的文件上传的,本文Flash上传文件的实现原理是:

通过Flash和页面中的Javascript通信(这时候是Flash->Javascript),调用JavaScript控制一个隐藏的含有文件域的表单,发送文件数据到后台程序页面(asp,aspx,php等),后台程序接收到上传的文件数据后,进行保存等处理,最后反馈信息给Flash(这时候就是Javascript->Flash)。

我们先来看下面这个截图:

这是一个Flash界面,可以“实现文件上传”,并进行相应提示(成功/失败),下面我们就来制作这样的程序。

二、准备工作。
本文的目的就是教大家制作这样功能的Flash程序,在进行之前,我们需要一些技术上的准备,我们需要知道:
·Flash如何调用Html页面中的JavaScript?
·JavaScript如何发送数据给Flash?

1. Flash如何调用Html页面中的JavaScript?(Flash->Javascript)
下面介绍两种方法:
A.在Flash中使用getURL 函数:

getURL 函数的原义是,在指定的Html页面框架(frame)中,打开指定的网页。
这里,我们把url网址写成一段Javascript脚本即可在页面中执行,如:
getURL("Javascript:alert('OK')");
这句的执行效果相当于在Html中的:

<script>
alert(
"OK");
</script>

在Flash中使用getURL函数,可以调用当前Html页面中的任何Javascript脚本。

B.在Flash中使用fscommand函数:
fscommand(command:String, parameters:String) : Void

在Web浏览器中,fscommand()执行后将调用JavaScript函数moviename_DoFScommand,该函数位于包含 SWF文件的Web页中。moviename为用于EMBED标签的NAME属性或OBJECT标签的ID属性。
如:我们对SWF文件指定OBJECT标签的ID=myMovie,则调用JavaScript函数myMovie_DoFScommand
在这种用法下,commandparameters参数可以是任意的字符串或表达式。

如Flash中执行:

fscommand("upload""");

则web页中的:

function FlashUpload_DoFScommand(command, args) {
}

函数将被执行,两个函数的参数依次相对应,即会有command="upload",args="";

另外,在web页中使用fscommand时,还应该指定一个参数swLiveConnect=true,如:


<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="445" height="50" id="FlashUpload" align="middle">
    <param name="movie" value="FlashUpload.swf" />
    <param name="allowScriptAccess" value="always" />
    <param name="swLiveConnect" value="true" />
    <embed src="FlashUpload.swf" width="445" allowScriptAccess="always" height="50" name="FlashUpload" align="middle" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" 
swLiveConnect="true"/>
  </object>

 swLiveConnect属性的含义是:指定此参数会让Flash Player在第一次加载时,启动Java,从而使fscommand可以起作用。

2. JavaScript如何发送数据给Flash? (Javascript->Flash)
方法是在Javascript中使用SetVariable。
语法:SetVariable( variableName, value ) 

如下这段Javascript脚本的执行后会将Flash中名为txtbox的变量值修改为"1234":

var flash = document.getElementById("FlashObjectId");
 flash.SetVariable("txtbox", "1234");

更多关于Flash和Javascript通信的内容,可以看这里:
JavaScript 和 Flash 的通信
FLASH与JAVASCRIPT的通信

三、制作Flash。
启动Flash,新建一个空白文档,命名为:FlashUpload.fla;



如上图所示,场景背景色设为绿色,然后放置两个“动态文本”框:
上边带框线的文本框变量设置为:file,制作一个“浏览”按钮与其组合后来模仿web页中的文件域;
下边的文本框变量设置为:msg,用来显示提示信息;
最后还有一个“上传”按钮。

“浏览”按钮上添加如图代码:


“上传”按钮上添加如图代码:


这里的Flash对Javascript通信我使用了fscommand,fscommand的参数内容可以任意,我们让“浏览”按钮传递“browser”字符串过去,“上传”按钮传递“upload”字符串。后边的web页中会根据这两个字符串来进行不同的操作。使用getURL时,浏览器会产生“哒”的声音,使用fscommand则不会产生声音。

完成后保存,编译(ctrl+enter),生成FlashUpload.swf文件。

四、将FlashUpload.swf文件插入FlashUpload.html文件。
创建一个html文件:FlashUpload.html,插入FlashUpload.swf,同时编写响应fscommand命令的Javascript函数:FlashUpload_DoFScommand,完整的html文件内容如下:

这里就是注意一些变量和值的使用,我用不同的颜色做了标识。下一步要出现的Upload.aspx文件被放置在一个宽、高、边框均为0的Iframe里,达到隐藏效果。

Flash中的fscommand使用执行后,web页中的FlashUpload_DoFScommand函数会被执行,此函数中又对隐藏的Iframe进行操作,从而进行文件上传。

五、Upload.aspx:文件保存页面。

<%@ Page Language="C#" %>
<script runat="server">
protected override void  OnLoad(EventArgs e){
    
if (IsPostBack)
    
{
        
string msg = string.Empty;
        
try
        
{
            
if (File1.PostedFile.ContentLength > 0)
            
{
                
//在此进行文件合法性判断,然后进行保存.
                
//
                
//File1.PostedFile.SaveAs(@"C:\abc.ext");
                
                msg 
= "文件" + File1.PostedFile.FileName.Replace(@"\"@"\\"+ "(" + File1.PostedFile.ContentLength.ToString() + "字节)上传成功.";
            }

            
else
            
{
                msg 
= ("请选择一个有效的文件.");
            }
  
        }

        
catch
        
{
            msg 
= "上传文件失败.";
        }


        
this.RegisterClientScriptBlock("setFlash""<script>setFlash('msg','" + msg + "');<" + "/script>");
    }

}

</script>

<html>
<head>
    
<title>SaveFile</title>    
    
<script language=javascript>
    
//javascript->flash
    var flash = parent.document.getElementById("FlashUpload");
    function setFlash(obj,value)
    
{
        flash.SetVariable(obj, value);
    }

    
</script>
</head>
<body bgcolor="#99ff33">
    
<form id="form1" runat="server">
    
<div>
        
<input id="File1" runat="server" type="file" onChange="setFlash('file',this.value);"/></div>
    
</form>
</body>
</html>

这个页的内容比较简单,目的是用来接收数据并保存,单独运行效果如下:

因为这个页面中表单的提交是通过Flash调用Javascript脚本来进行的,所以这个页面中没有提交按钮,假如有提交按钮,这个页本身应该可以进行文件上传。最后这个页是被放置在一个隐藏的IFrame框架中的,用户并不可见。

需要注意是就是这个页中使用SetVariable向Flash发送数据(回馈信息)。

完成后的整体运行效果,就是本文开头的那张图片。

本文示例在Flash8+.Net1.1下制作并在IE下测试通过。
 
本文完整的源代码下载(122K)>>


(由于文件上传的特殊性,Flash上传文件必须这么“麻烦”的调用Javascript 和隐藏的表单来完成。除此之外,Flash是支持直接Post数据到一个aspx页面的,如使用sendAndLoad方法。另外有国外闪客写了一个yamzbrowser的Flash插件,能够使用Flash实现文件上传功能,但原理也基于此。)
posted on 2007-02-24 22:50 三千 阅读(9552) 评论(31)  编辑 收藏 所属分类: [D]. ASP.NET[I ]. Flash技术[K]. JavaScript

评论:
#1楼  2007-02-25 08:39 | Yok      
flash9可以上传文件了
  回复  引用  查看    
#2楼  2007-02-25 08:46 | JesseZhao      
不错,昨天看了那个上传大文件的文章感觉就是很好,嘿嘿
  回复  引用  查看    
#3楼  2007-02-25 08:47 | JesseZhao      
@Yok
是不是flash9直接就带上传的控件啊?
  回复  引用  查看    
#4楼  2007-02-25 08:55 | JesseZhao      
感觉这种传小文件可以,大文件一定失败的

  回复  引用  查看    
#5楼  2007-02-25 09:04 | 浪子      
为什么不用Flash 的API(FileReference和FileReferenceList)呢?可以支持大文件上传http://www.cnblogs.com/walkingboy/archive/2007/02/09/Flash_FileUpload_FileReference.html
  回复  引用  查看    
#6楼  2007-02-25 09:22 | 深渊野鱼      
codeproject上面有一个flash批量上传的,也做得很不错.
  回复  引用  查看    
#7楼  2007-02-25 11:14 | Leepy      
我有一个flash的上传控件,有兴趣来下吧
http://www.cnblogs.com/liping13599168/archive/2007/02/25/655735.html
  回复  引用  查看    
#8楼 [楼主] 2007-02-25 12:21 | YAO.NET℡      
@Yok

flash9预览版出来很久了,一直没有尝试.不知道是否有这样的功能.

  回复  引用  查看    
#9楼 [楼主] 2007-02-25 12:25 | YAO.NET℡      
@JesseZhao
感觉这种传小文件可以,大文件一定失败的

如果配合asp.net做上传,传大文件就没有问题了,就象直接使用asp.net页上传文件一样。传大文件是与采用的后台页面语言的上传功能相关的。比如采用asp的无组上传,那肯定传不了大文件,如果让asp使用aspupload,sa-fileup等组件就又可以传大文件了。
  回复  引用  查看    
#10楼 [楼主] 2007-02-25 12:34 | YAO.NET℡      
@浪子

嗯。这个确实不错。但是FileReference API 支持最大100M的文件上传。
  回复  引用  查看    
#11楼  2007-02-25 13:24 | Tony Qu      
不错,希望有更多这样的文章,这样大家才能共同进步:)

顺便问一下,你用的Flash版本多少?是Flash MX 2004吗?还是更新的版本?不好意思,我好久没做Flash的东西了:p
  回复  引用  查看    
#12楼 [楼主] 2007-02-25 13:27 | YAO.NET℡      
@Tony Qu

我用的是Flash 8 。
Flash 9的预览版去年已推出可以在官方网下载,但正式版本还未推出。
  回复  引用  查看    
#13楼  2007-02-25 14:11 | 快乐笛子 [未注册用户]
能看到上传的进度吗?
  回复  引用  查看    
#14楼 [楼主] 2007-02-25 14:28 | YAO.NET℡      
@快乐笛子

本例没有上传进度。

可在此基础上继续开发实现上传进度显示。
浪子写的那个有上传进度,FileReference是从客户端获取上传进度的,象asp.net的上传进度是从服务端来反馈进度信息的。
  回复  引用  查看    
#15楼  2007-03-02 20:08 | fishert      
LoadVars("网页名?..")就可以传参数给相应的处理网页了,上传功能在.net,php,jsp,asp上做都没关系
  回复  引用  查看    
#16楼  2007-03-02 20:10 | fishert      
什么时候做Ria时有控件可以直连数据库就好了,最近用Flex,连数据库的话用RemoteObject连Java,通过Java连数据库
当然也可通过HTTPService接.net,asp...
  回复  引用  查看    
#17楼  2007-03-07 22:46 | 张振      
不错 正好想要找这个
  回复  引用  查看    
#18楼  2007-03-26 12:34 | 董乐 [未注册用户]
第一次发表FLASH,请大家多多指点
  回复  引用  查看    
#19楼  2007-03-29 20:34 | qwe [未注册用户]
wefwe
  回复  引用  查看    
#20楼  2007-04-07 02:47 | gyjhgj [未注册用户]
esfesgr
  回复  引用  查看    
#22楼  2007-04-18 03:16 | abc [未注册用户]
浪子大哥能在这个基础上做个断点续传吗
  回复  引用  查看    
#23楼  2007-05-17 14:04 | 匿名 [未注册用户]
本文是垃圾
传小文件干嘛要用 flash
asp.net 自带的上传控件岂不更好用
传大文件这个办法根本不行

鉴定完毕!
  回复  引用  查看    
#24楼 [楼主] 2007-05-17 19:17 | YAO.NET℡      
@匿名

不要激动呀,慢慢看清楚再讨论.

上传还是用asp.net页的呀,你说asp.net能上传大文件吗?

有些网站,ui都是用flash制作的,这时候要有一个统一的外观,或者有其它原因,上传界面要是flash制作的,这时候就不是文件大小的问题了.


  回复  引用  查看    
#25楼  2007-07-05 21:55 | 21212 [未注册用户]
<DIV><A href="http://u1.kubao.com/unionreg.aspx?unionid=900&amp;unionkey=29341239" target=_blank>免费发送短信</A> |&nbsp; <A href="http://u1.kubao.com/unionreg.aspx?unionid=900&amp;unionkey=29341239" target=_blank>多人电话会议 </A>|&nbsp; <A href="http://u1.kubao.com/unionreg.aspx?unionid=900&amp;unionkey=29341239" target=_blank>超低的国内</A>&nbsp;|&nbsp; <A href="http://u1.kubao.com/unionreg.aspx?unionid=900&amp;unionkey=29341239" target=_blank>国际长途话费</A>&nbsp;|&nbsp; <A href="http://u1.kubao.com/unionreg.aspx?unionid=900&amp;unionkey=29341239" target=_blank>炫酷彩语</A> </DIV>
  回复  引用  查看    
#26楼 [楼主] 2007-07-19 13:46 | YAO.NET(三千)℡      
@21212
没有病毒我也不进去.:D

  回复  引用  查看    
#27楼  2007-08-20 23:10 | 路人甲 [未注册用户]
这种方法可以实现用Flash取得上传文件的大小吗?
  回复  引用  查看    
#28楼 [楼主] 2007-08-22 12:45 | 三千.℡      
@路人甲

上传文件大小在客户端直接不能取得,需要从服务端取得后再返回flash.
若要直接取得,可以使用FileReference 类.


  回复  引用  查看    
#29楼  2008-03-21 13:55 | ywcq [未注册用户]
请问文件上传到哪里去了?
比如 http://hpccmd.changlai.cn/下的哪个文件夹

  回复  引用  查看    
#30楼 [楼主] 2008-03-22 23:12 | 三千      
@ywcq

文件传到那儿,在于你:
//File1.PostedFile.SaveAs(@"C:\abc.ext");
这句的保存位置和网站路径的映射.

比如,如果你将c:\website\upload文件夹和http://hpccmd.changlai.cn/upload
映射,那么File1.PostedFile.SaveAs(@"c:\website\upload\abc.ext");就相当于你所说的上传到了http://hpccmd.changlai.cn/upload啦.


  回复  引用  查看    
#31楼  2008-06-24 10:10 | 张城镇 [未注册用户]
型号
(高*宽)mm 截面尺寸 截面面积cm2 理论面积Kg/m
H*B T1 T2 R
100*100 100*100 6 8 8 21.59 16.9
125*125 125*125 6.5 9 8 30 23.6
150*150 150*150 7 10 8 39.65 31.1
150*75 150*75 5 7 8 17.85 14
200*100 198*99 4.5 7 8 22.69 17.8
200*100 5.5 8 8 26.67 20.9
250*125 248*124 5 8 8 31.99 25.1
250*125 6 9 8 36.97 29
150*100 148*100 6 9 8 26.35 20.7
200*150 194*150 6 9 8 38.11 29.9
350*150 350*150 6.5 9 13 46.78 36.7
100*50 100*50 5 7 8 11.85 9.3
125*60 125*60 6 8 8 16.69 13.1
240*120 240*120 6.2 9.8 8 39.1 30.7
270*135 270*135 6.6 10.2 8 45.9 36.1

  回复  引用  查看