天天看点

flash 多个文件上传

像flickr一样多选图片一次上传

做上传图片功能的时候,经常会遇到这样一个问题,有时候可能需要一次上传多张图片,而用html中默认的上控件,却只能选定一个文件,且不能对文件的后缀进行筛选。需要一次上传多个文件的需求,往往可以通过添加多个上传控件来予以满足,比如百度空间的相册上传功能就是这样来实现的。不过,要实现对上传文件后缀的过滤,却始终无法通过常规的方法予以实现。

这两个功能真的这么难以实现吗?非也,看看flickr的上传功能即可获得明确的答复。

为什么能实现这样的功能呢?google了一下,谜底就揭晓了。原来,这是利用了flash的若干功能,通过javascript和actionscript的交互得以实现的。js和as的通讯以前有研究过,所以要实现起来非常简单。再到flash里边f1一下,关于上传方面的相关只是也差不多了解了,因此,接下来的事情的就只是顺水推舟的事情了。

最重要的还是flash代码的完善,最后的成果如下:

// MultiUploader.fla

import flash.net.FileReferenceList;

import flash.net.FileReference;

import flash.external.ExternalInterface;

// 设置as中函数和js调用时的映射关系

ExternalInterface.addCallback("fu_open_dialog", null, openDialog);

ExternalInterface.addCallback("fu_begin_upload", null, beginUpload);

// 可以通过html页面里边设置FlashVars里边的upload_url来更改上传文件的路径

var uploadUrl:String = typeof(_root.upload_url) == "undefined" ? "FlashUpload.ashx" : _root.upload_url;

var listener:Object = new Object();

// 选择文件后,会视图调用js函数onUploaderSelect,并将文件列表传入进去,便于js进一步做一些逻辑控制

listener.onSelect = function(fileRefList:FileReferenceList) {

  ExternalInterface.call("onUploaderSelect", fileRefList.fileList);  

};

var fileRefList:FileReferenceList = null;

var imageTypes:Object = new Object();

imageTypes.description = "Images (*.jpg, *.jpeg, *.gif, *.png)"; // 上传文件类型说明

imageTypes.extension = "*.jpg; *.jpeg; *.gif; *.png"; // 控制上传文件类型

// 显示文件打开窗口

function openDialog():Void {

  if (fileRefList == null) {

  fileRefList = new FileReferenceList();

  fileRefList.addListener(listener);

  }

  fileRefList.browse([imageTypes]);

}

// 开始上传

function beginUpload():Void {

  var lis = new Object();

  // 每上传完一个文件后调用js函数onUploaderComplete

  lis.onComplete = function(file:FileReference):Void {

  ExternalInterface.call("onUploaderComplete", file.name);  

  };

  // 处理上传地址的http状态错误。比如404等。

  lis.onHTTPError = function(file:FileReference, httpError: Number):Void {

  ExternalInterface.call("onUploaderHTTPError", httpError, file.name);

  var list:Array = fileRefList.fileList;

  var item:FileReference;

  // 最终还是将文件分单次传到指定上传页面进行处理

  for(var i:Number = 0; i < list.length; i++) {

  item = list;

  item.addListener(lis);

  item.upload(uploadUrl);

至于客户端的处理,只需要将as中自动调用的几个js函数实现即可。最后的页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

<input type="button" value="open" onclick="openUploadDialog();"/>

<input type="button" value="upload" onclick="uploadFiles();"/>

<div id="flashPanel"></div>

</body>

<script type="text/javascript">

var flash = createUploadFlash(document.getElementById('flashPanel'), 'upload.swf', 'FlashUpload.ashx')

// 打开文件对话框

function openUploadDialog() {

  flash.fu_open_dialog();

// 上传文件

function uploadFiles() {

  flash.fu_begin_upload();

// 选择文件以后

function onUploaderSelect(list) {

  alert(list);

// 上传完一个文件以后

function onUploaderComplete(name) {

  alert(name);   

// 上传文件出错时

function onUploaderHTTPError(number, name) {

  switch (number) {

  case 413:

  alert("文件" + name + "大于10K,不能上传");

  break;   

/**

* 创建一个flash。主要是在ie7里边需要用鼠标点击才能激活flash,通过动态生成flash的方式可以绕过这一点。

* @param panel 用来放置flash的div

* @param flashUrl flash的地址

* @param uploadUrl 用来出来上传文件的地址

*/

function createUploadFlash(panel, flashUrl, uploadUrl){

  var code = '<object classid="clsid

flash 多个文件上传

27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="0" height="0" id="flashObject" align="middle">\

  <param name="allowScriptAccess" value="sameDomain" />\

  <param name="movie" value="' + flashUrl + '" />\

  <param name="quality" value="high" />\

  <param name="bgcolor" value="#ffffff" />\

  <param name="FlashVars" value="upload_url=' + uploadUrl + '" />\

  <embed src="' + flashUrl + '" quality="high" bgcolor="#ffffff" width="0" height="0" name="flashObject" FlashVars="upload_url=' + uploadUrl + '" align="middle" allowScriptAccess="sameDomain" id="flashObject" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />\

  </object>';

  panel.innerHTML = code;

  return window.document.flashObject;

</script>

</html>

这次功能的实现上,在其他方面都还很顺利得以实现,反而是在createUploadFlash这个函数的实现上遇到了一些麻烦。因为最后返回flash对象的时候经常不被正常地识别。如果这段代码不用js生成,那么用document.flashObject和dobument.getElementById('flashObject')都可以正常识别flashObject,但动态生成以后,用后者就不能正常被访问到了,可能的原因是加载需要一定的延时,有待研究。