天天看點

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,但動态生成以後,用後者就不能正常被通路到了,可能的原因是加載需要一定的延時,有待研究。