熱烈祝賀臺州維博網絡的站長論壇隆重上線!(2012-05-28)    熱烈慶祝偉大的祖國60周年生日 點擊進來我們一起為她祝福吧(2009-09-26)    站長論壇禁止發布廣告,一經發現立即刪除。謝謝各位合作!.(2009-08-08)    熱烈祝賀臺州網址導航全面升級,全新版本上線!希望各位一如既往地支持臺州網址導航的發展.(2009-03-28)    臺州站長論壇恭祝各位新年快樂,牛年行大運!(2009-01-24)    臺州Link正式更名為臺州網址導航,專業做以臺州網址為主的網址導航!(2008-05-23)    熱烈祝賀臺州Link資訊改名為中國站長資訊!希望在以后日子里得到大家的大力支持和幫助!(2008-04-10)    熱烈祝賀臺州Link論壇改名為臺州站長論壇!希望大家繼續支持和鼓勵!(2008-04-10)    臺州站長論壇原[社會瑣碎]版塊更名為[生活百科]版塊!(2007-09-05)    特此通知:新臺州站長論壇的數據信息全部升級成功!">特此通知:新臺州站長論壇的數據信息全部升級成功!(2007-09-01)    臺州站長論壇對未通過驗證的會員進行合理的清除,請您諒解(2007-08-30)    臺州網址導航|上網導航誠邀世界各地的網站友情鏈接和友誼聯盟,共同引領網站導航、前進!(2007-08-30)    禁止發廣告之類的帖,已發現立即刪除!(2007-08-30)    希望各位上傳與下載有用資源和最新信息(2007-08-30)    熱烈祝賀臺州站長論壇全面升級成功,全新上線!(2007-08-30)    
便民網址導航,輕松網上沖浪。
臺州維博網絡專業開發網站門戶平臺系統
您當前的位置: 首頁 » PHP/Perl編程 » PHP+Flash多文件異步上傳swfupload

PHP+Flash多文件異步上傳swfupload

論壇鏈接
  • PHP+Flash多文件異步上傳swfupload
  • 發布時間:2010-03-31 16:36:02    瀏覽數:20755    發布者:sunhw0725    設置字體【   
什么是SWFUpload?
  SWFUpload是一個客戶端文件上傳工具,最初由Vinterwebb.se開發,它通過整合Flash與JavaScript技術為WEB開發者提供了一個具有豐富功能繼而超越傳統<input type="file" />標簽的文件上傳模式。官方地址:http://www.swfupload.org

SWFUpload的主要特點
  * 可以同時上傳多個文件;
  * 類似AJAX的無刷新上傳;
  * 可以顯示上傳進度;
  * 良好的瀏覽器兼容性;
  * 兼容其他JavaScript庫 (例如:jQuery, Prototype等);
  * 支持Flash 8和Flash 9;
  SWFUpload不同于其他基于Flash構建的上傳工具,它有著優雅的代碼設計,開發者可以利用XHTML、CSS和JavaScript來隨心所欲的定制它在瀏覽器下的外觀;它還提供了一組簡明的JavaScript事件,借助它們開發者可以方便的在文件上傳過程中更新頁面內容來營造各種動態效果。
  在使用SWFUpload之前,請確認你具備一定的JavaScript和DOM知識。在實際開發中,大部分的錯誤都是由于錯誤的設置和低劣的Event Handlers處理程序所造成的。

文檔中文翻譯
  http://www.v-sky.com/doc/swfupload/v2.1.0/Documentation.html

效果演示
  * Classic Form Demo http://demo.swfupload.org/formsdemo ;
  * Features Demo http://demo.swfupload.org/featuresdemo ;
  * Application Demo http://demo.swfupload.org/applicationdemo ;
  * v1.0.2 Plugin Demo http://demo.swfupload.org/v102demo ;

選擇合適的Flash控件
  在發行包(SWFUpload v2)中含有2個版本的Flash控件(swfupload_f8.swf 與wfupload_f9.swf),其中第一個版本擁有最佳的兼容性,但是為此損失了部分功能;而第二個版本提供了一些附加的功能但是損失了兼容性。

SWFUpload的初始化與配置
  首先,在頁面中引用SWFUpload.js ,如
  <script type="text/javascript" src="http://www.swfupload.org/swfupload.js"></script>
  然后,初始化SWFUpload ,如
  var swfu;
  window.onload = function () {
  swfu = new SWFUpload({
  upload_url : "http://www.swfupload.org/upload.php",
  flash_url : "http://www.swfupload.org/swfupload_f9.swf", file_size_limit : "20480"
  });
  };
  以下是一個標準的SWFUpload初始化設置所需的參數,你可以根據需要自己進行刪減:
  {
  upload_url : "http://www.swfupload.org/upload.php", 處理上傳請求的服務器端腳本URL
  file_post_name : "Filedata", 是POST過去的$_FILES的數組名
  post_params : {
  "post_param_name_1" : "post_param_value_1",
  "post_param_name_2" : "post_param_value_2",
  "post_param_name_n" : "post_param_value_n"
  },
  file_types : "*.jpg;*.gif", 允許上傳的文件類型
  file_types_description: "Web Image Files", 文件類型描述
  file_size_limit : "1024", 上傳文件體積上限,單位MB
  file_upload_limit : 10, 限定用戶一次性最多上傳多少個文件,在上傳過程中,該數字會累加,如果設置為“0”,則表示沒有限制
  file_queue_limit : 2, 上傳隊列數量限制,該項通常不需設置,會根據file_upload_limit自動賦值
  flash_url : "http://www.swfupload.org/swfupload_f9.swf", Flash控件的URL
  flash_width : "1px",
  flash_height : "1px",
  flash_color : "#FFFFFF",
  debug : false, 是否顯示調試信息
  swfupload_loaded_handler : swfupload_loaded_function, 當Flash控件成功加載后觸發的事件處理函數
  file_dialog_start_handler : file_dialog_start_function, 當文件選取對話框彈出前出發的事件處理函數
  file_queued_handler : file_queued_function,
  file_queue_error_handler : file_queue_error_function,
  file_dialog_complete_handler : file_dialog_complete_function, 當文件選取對話框關閉后觸發的事件處理函數
  upload_start_handler : upload_start_function, 開始上傳文件前觸發的事件處理函數
  upload_progress_handler : upload_progress_function,
  upload_error_handler : upload_error_function,
  upload_success_handler : upload_success_function, 文件上傳成功后觸發的事件處理函數
  upload_complete_handler : upload_complete_function,
  debug_handler : debug_function,
  custom_settings : { 自定義設置
  custom_setting_1 : "custom_setting_value_1",
  custom_setting_2 : "custom_setting_value_2",
  custom_setting_n : "custom_setting_value_n",
  }
  }
SWFUpload中的File Object
  在SWFUpload的使用過程中,無論在客戶端還是服務器端都要和File Object打交道,在一個File Object中包含了以下內容:
  {
  id : string, // SWFUpload file id, used for starting or cancelling and upload
  index : number, // The index of this file for use in getFile(i)
  name : string, // The file name. The path is not included.
  size : number, // The file size in bytes
  type : string, // The file type as reported by the client operating system
  creationdate : Date, // The date the file was created
  modificationdate : Date, // The date the file was last modified
  filestatus : number, // The file's current status. Use SWFUpload.FILE_STATUS to interpret the value.
  }
SWFUpload中的方法
  + setPostParams (param_object)
  - 描述
  動態修改SWFUpload初始化設置中的post_params屬性,其中所有的值都將被覆蓋。
  - 參數
  param_object:一個simple JavaScript object,所有的name/value都必須是字符串,例如(this.setPostParams({ "Mari": name });)。
  - 返回
  void
SWFUpload中的事件
  SWFUpload在運行過程中提供了多種事件,這些事件可以讓開發者借助句柄來改變頁面UI、改變行為,或者報告錯誤。所有這些事件都可以在一個SWFUpload實體中被調用,這意味著在這些事件對應的函數中,你可以用 this 關鍵字來代替引用SWFUpload實體。
  + fileDialogComplete (number of files selected)
  - 觸發條件
  1. 用戶選擇好了要上傳文件,并關閉對話框;
  2. 用戶什么也沒選,并取消對話框;
  如果你希望在用戶選擇完文件后自動開始上傳操作,那么可以將 this.startUpload() 操作放在這里。
  - 傳入參數
  number of files selected:將返回用戶所選取的文件個數。
  + uploadStart (file object)
  - 觸發條件
  該事件在文件上傳之前觸發,它用于完成一些準備工作,比如傳遞參數;負責響應該事件的句柄函數可以有2個返回值(true 或 false)當返回值為false時,整個上傳將被取消;當返回值為true時上傳過程繼續進行。而如果返回值為false,則通常是由一個uploadError事件所導致的。
  注:官方幫助文檔的原文中對該事件的描述中有這樣一句:“If you return 'true' or do not return any value then the upload proceeds.”,從中可以看到既定的設計是當不返回任何值的時候應該等同于返回true,但是筆者在開發中發現必須明確返回值,否則上傳進程將停止響應,不知是否是一個bug呢?
  - 傳入參數
  file object:文件對象
  + uploadComplete (file object)
  - 觸發條件
  在完成一個上傳周期后(在uploadError 或 uploadSuccess之后),此時一個上傳操作已經結束,另一個上傳操作可以開始了。
  - 傳入參數
  file object:文件對象
  + uploadProgress (file object, bytes complete, total bytes)
  - 觸發條件
  該事件在整個文件的上傳過程中定期性的被Flash控件自動觸發,用以幫助開發者實時更新頁面UI來制作上傳進度條。
  注意:該事件在Linux版本的Flash Player中存在問題,目前還無法解決。
  - 傳入參數
  file object:文件對象
  bytes complete:已經上傳完畢的文件字節數
  total bytes:文件總體積的字節數
常見錯誤
  ■ 所上傳的文件體積并未超出SWFUpload所設置的數值,但為何無法成功上傳?
  □ 通常這是由于服務器端的限制所造成的,以Apache+PHP為例,請修改php.ini中的post_max_size與upload_max_filesize兩項設置。
  ■ 在帶有Session驗證的網站后臺中SWFUpload無法正常工作?
  □ 這是因為SWFUpload在上傳時相當于重新開辟了一個新的Session進程,因此無法與原有程序的Session保持一致,這就需要在上傳時傳遞原有程序的SessionID,根據它來“找回”其應有的Session。
  ■ 關于swfupload上傳中文文件名亂碼的問題
  □ 實際上是由于編碼的問題造成的,程序使用的utf-8,文件名傳遞時也是這種編碼,因此造成亂碼或文件不能保存,僅是需要修改接收文件,以PHP為例,upload.php中
  $file_name = $_FILES[$upload_name]['name'];
  $file_name=iconv("UTF-8","GB2312",$file_name);
  這樣即可解決。
      swfUpload注意事項

在使用swfupload上傳文件的時候,老是繞不過登錄驗證。查了一下GOOGLe,沒查到,問了百度,他告訴我答案:

swfuplaod在上傳時,會新開一個進程,和原來的進程不一致,要解決這個問題,需要指定session_id,然后在登錄頁面判斷,如果有post過來的session_id,那么就用函數session_id( $_POST['PHP_SESSIONID'])指定一下。

上傳頁的JS里面,可以獲取當前的SESSION_ID的。

例如上傳頁的JS中:

post_params: {"PHPSESSID": "<?php echo session_id(); ?>"},

在驗證的判斷頁中:

if (isset($_POST["PHPSESSID"])) {
session_id($_POST["PHPSESSID"]);
}

(這一段是網上的注釋:在帶有Session驗證的網站后臺中SWFUpload無法正常工作,這是因為SWFUpload在上傳時相當于重新開辟了一個新的Session 進程,因此無法與原有程序的Session保持一致,這就需要在上傳時傳遞原有程序的SessionID,根據它來“找回”其應有的Session。)
      由于項目需要,這兩天研究了一下SWFUpload,一個JS和AS結合實現的上傳“功能包”,簡單來說原理就是利用flash的FileReference類在客戶端完成文件信息的過濾,包括類型、大小,以及上傳的實時進度信息,然后利用externalInterface來跟客戶端的JS通信,提供了一系列屬性、方法和事件觸發時的回調函數接口,將UI的主動權完全由FLASH轉交給了JS來操作。(PS:目前版本還沒有Release,有些功能和文檔還不全,疑惑之處可直接翻代碼看看。等我項目結束時希望SWFUpload放出正式版和官方確定的接口文檔了,到時再針對傳統文件上傳的各種方式和SWFUpload功能包嘮叨幾句。)這里只嘮叨一下目前這個版本存在的一個BUG,在IE6內核的多標簽瀏覽器中(例如GreenBrowser和Maxthon),一旦頁面刷新過后,SWFUpload的功能就不正常了,或許你也正為這個發愁了,可以先跳到這里察看臨時解決方案。

  最初用SWFUpload做demo的時候就發現了目前存在一個小BUG:我機器上的瀏覽器環境是GreenBrowser(IE6內核),打開上傳頁面,一切功能都正常,此時如果刷新或者強刷一下頁面,那么當點擊文件瀏覽按鈕時(觸發selectFile事件),debug信息中就會提示“Could not find Flash element”,而在FF、IE7下面功能很正常,更奇怪的是在我隨后的debug過程中我發現在單獨的IE6,也就是系統提供的那個單窗口的IE6下居然功能也很正常。后來又在ie6內核下測試了maxthon同樣存在和GreenBrowser一樣的問題,難道這個跟多標簽瀏覽器也有關系?第一反應是我的demo有問題。于是去SWFUpload的官方demo驗證了下,發現居然也存在這個問題。哎~又是IE惹的禍。開始Debug之旅吧。

  一、首先用DOM察看器在IE下看看刷新前后DOM元素中flash元素的變化
  有了FireBug以后,讓IE下的幾個調試工具顯得太簡陋了,不過至少我還可以直接察看到DOM元素的變化。奇怪的是刷新前后,FLASH元素都完整地出現在DOM中,那為何會提示“Could not find Flash element”呢?
  
  二、 跟蹤文件瀏覽的點擊事件selectFile
  到SWFUpload庫中能看到擴展了一個selectFile的方法。



SWFUpload.prototype.selectFile = function () {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SelectFile) === "function") {
try {
movie_element.SelectFile();
}
catch (ex) {
this.debug("Could not call SelectFile: " + ex);
}
} else {
this.debug("Could not find Flash element");
}

};

SWFUpload.prototype.selectFile = function () {
var movie_element = this.getMovieElement();
if (movie_element !== null && typeof(movie_element.SelectFile) === "function") {
try {
movie_element.SelectFile();
}
catch (ex) {
this.debug("Could not call SelectFile: " + ex);
}
} else {
this.debug("Could not find Flash element");
}

};  難道“Could not find Flash element”是這里輸出來的?于是將這個語句給注釋掉再測試,果然沒有看到“沒有找到flash元素”的debug信息了,這就確定了是這個方法里出現了異常,仔細看了下這個if判斷,這里不但對flash元素的存在性做了判斷,還需要判斷flash元素里是否存在SelectFile方法。個人覺得這個雙保險檢測是沒有錯,但這個debug信息未免就太籠統了,typeof(movie_element.SelectFile) === "function" 如果是false那也不能說明是flash元素不存在。之前我總結flash和js通信的時候也做過externalInterface的demo,猜測一下這里的實現原理:SelectFile方法是externalInterface類用addCallback方法在 flash中將一個名為SelectFile的方法注冊到容器中可供JS調用,也就是現在看到的這種形式movie_element.SelectFile()。那么理論上如果flash元素存在,那么typeof(movie_element.SelectFile) === "function"肯定是true,可是在IE6這個總是很另類但又是用戶占有率最高的瀏覽器里這個理論還真就出問題了,下面可以來證明一下。

  三、觀察瀏覽器刷新前后movie_element.SelectFile的變化
  重新打開一個新頁面測試SWFUpload的官方demo,測試文件瀏覽功能,正常。于是在地址欄輸入

javascript:alert(document.getElementById("SWFUpload_0").SelectFile);void 0;

javascript:alert(document.getElementById("SWFUpload_0").SelectFile);void 0;

(PS:IE下的調試方法實在是太簡陋了,還好廣大開發者的智慧是無窮的。)
這里的SWFUpload_0是SWFUpload生成的flash元素時指定的id,這個可以從dom節點中看到。如果你想更詳細地確認其中細節可以看SWFUpload中的initSWFUpload方法,事實上這里會有一個實例隊列,因為這個demo中就是一個實例,所以這個flash的id在隊列中是SWFUpload_0;剀噲绦猩厦娴腏S,正常情況下你會看到如下信息:

function () { return eval(instance.CallFunction("<invoke name=\""+name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>")); }

function () { return eval(instance.CallFunction("<invoke name=\""+name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>")); }

  從這段代碼的特征上也驗證我之前的猜測,SelectFile確實是flash中注冊的一個方法。
然后刷新此頁面,再到地址欄輸入回車,HOHO你會得到undefined信息。SWFUpload的開發者可能也沒有想到理論上很保險的做法到IE6下會有如此怪異的行為。Flash還存在,為什么其中addCallback注冊的方法會“消失”呢?難道是externalInterface類本身有問題?于是又把自己以前的一個demo拿出來測試,發現刷新前后功能依然很正常,匪夷所思。仔細對比了下兩個demo的差異,最后將疑點鎖定在了flash的寫入方式,SWFUpload是用JS將flash寫入到dom中的,我自己的demo中flash元素是直接寫死在HTML代碼里的。

  四、測試不同的flash寫入方式對addCallback方法的影響
  AW說SWFUpload中寫入flash的方法是從SWFObject庫里抽出來的,這個SWFObject的官方說明也證實了這點。打開SWFUpload庫確實也可以看到SWFObject的幾個核心方法。那這就確定了SWFUpload寫入flash和SWFObject原理上一樣的,于是采用SWFobject對我之前的demo做測試。
  1、首先用最原始的方法將flash靜態寫入到頁面中(察看實例)
  關于靜態插入flash到頁面的不同方式的細節以及他們對JS造成的影響隨后再寫個詳細的東東,這里先不做具體探討,暫且使用最常用的object和embed混合的方式。
  第一個按鈕是js調用as中注冊的say方法;
  第二個按鈕是測試flash元素是否在頁面中,如果在頁面中,那么打印出他的innerHTML屬性;
  第三個按鈕是測試flash元素中addCallBack注冊的方法是否還存在,如果存在那么將其打印出來;
  當頁面第一次打開的時候分別點擊三個按鈕,callback注冊的say方法呼叫正常,flash元素存在,其中注冊的say方法也存在。
  下面將頁面刷新一次再測試,測試結論和剛才一樣,都很正常。這就確保了我目前采用的flash中addCallBack注冊的say方法功能是正常的。

  2、利用SWFObject寫入flash到頁面中(察看實例)
  同樣測試刷新前后的變化,刷新前功能正常,而將頁面刷新一次再測試,就跟我之前描述的bug一樣,怪異現象出現了,callback注冊的say方法呼叫失敗了,flash元素是存在的,但其中注冊的say方法也不見了。
到這步為止已經找到辦法解決項目中遇到的SWFUpload的刷新BUG了,將SWFUpload中寫入flash的方法變成靜態寫入即可,事實上當時考慮項目進度我確實是這么做的,嘿嘿,盡管方法太笨。由于SWFUpload實例有很多設置需要配置到FlashVars中,所以做這個靜態寫入時最好先將SWFupload的getFlashHTML方法返回值打印出來(PS:需要針對IE和之外的瀏覽器,實際上就是Object和embed兩種不同flash的插入方式做一個判斷輸出,切忌不能將他們同時寫入頁面,否則會造成SWFUpload無法正確找到實例的flash元素。)

  上面的解決方案只是曲線救國,考慮到以后項目中的靈活使用和維護,還是需要把其中的問題找出來,再回到我們的Debug進程來,F在已經證明問題出在flash的寫入方式上。刨開SWFObject的代碼能夠很清晰看出它的原理:根據實例化時的最基本參數配置和屬性、flashvars設置方法來針對object和embed兩種不同的插入方法構造出兩個不同的flashDom節點。當write方法調用時,將此節點寫入到目標容器的innerHTML中。難道是innerHTML在作怪?

  五、跟蹤innerHTML寫入flash節點
  還是針對上面的demo做測試,將SWFObject調用write前構造出來的flash節點字符串和write之后瀏覽器里flash節點的html代碼分別打印出來比較。

IE6:
Write調用前:
<object id="demo" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="300" height="100" style="undefined"><param name="movie" value="demo.swf" /><param name="bgcolor" value="#fff" /><param name="quality" value="high" /></object>

Write調用后:
<OBJECT id=demo height=100 width=300 classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000><PARAM NAME="_cx" VALUE="7938"><PARAM NAME="_cy" VALUE="2646"><PARAM NAME="FlashVars" VALUE=""><PARAM NAME="Movie" VALUE="demo.swf"><PARAM NAME="Src" VALUE="demo.swf"><PARAM NAME="WMode" VALUE="Window"><PARAM NAME="Play" VALUE="0"><PARAM NAME="Loop" VALUE="-1"><PARAM NAME="Quality" VALUE="High"><PARAM NAME="SAlign" VALUE=""><PARAM NAME="Menu" VALUE="-1"><PARAM NAME="Base" VALUE=""><PARAM NAME="AllowScriptAccess" VALUE=""><PARAM NAME="Scale" VALUE="ShowAll"><PARAM NAME="DeviceFont" VALUE="0"><PARAM NAME="EmbedMovie" VALUE="0"><PARAM NAME="BGColor" VALUE=""><PARAM NAME="SWRemote" VALUE=""><PARAM NAME="MovieData" VALUE=""><PARAM NAME="SeamlessTabbing" VALUE="1"><PARAM NAME="Profile" VALUE="0"><PARAM NAME="ProfileAddress" VALUE=""><PARAM NAME="ProfilePort" VALUE="0"><PARAM NAME="AllowNetworking" VALUE="all"><PARAM NAME="AllowFullScreen" VALUE="false"></OBJECT>

IE6:
Write調用前:
<object id="demo" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="300" height="100" style="undefined"><param name="movie" value="demo.swf" /><param name="bgcolor" value="#fff" /><param name="quality" value="high" /></object>

Write調用后:
<OBJECT id=demo height=100 width=300 classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000><PARAM NAME="_cx" VALUE="7938"><PARAM NAME="_cy" VALUE="2646"><PARAM NAME="FlashVars" VALUE=""><PARAM NAME="Movie" VALUE="demo.swf"><PARAM NAME="Src" VALUE="demo.swf"><PARAM NAME="WMode" VALUE="Window"><PARAM NAME="Play" VALUE="0"><PARAM NAME="Loop" VALUE="-1"><PARAM NAME="Quality" VALUE="High"><PARAM NAME="SAlign" VALUE=""><PARAM NAME="Menu" VALUE="-1"><PARAM NAME="Base" VALUE=""><PARAM NAME="AllowScriptAccess" VALUE=""><PARAM NAME="Scale" VALUE="ShowAll"><PARAM NAME="DeviceFont" VALUE="0"><PARAM NAME="EmbedMovie" VALUE="0"><PARAM NAME="BGColor" VALUE=""><PARAM NAME="SWRemote" VALUE=""><PARAM NAME="MovieData" VALUE=""><PARAM NAME="SeamlessTabbing" VALUE="1"><PARAM NAME="Profile" VALUE="0"><PARAM NAME="ProfileAddress" VALUE=""><PARAM NAME="ProfilePort" VALUE="0"><PARAM NAME="AllowNetworking" VALUE="all"><PARAM NAME="AllowFullScreen" VALUE="false"></OBJECT>

  顯然,IE瀏覽器對object便簽做了很多處理,innerHTML強大功能的背后到底隱藏了什么?起初我懷疑是innerHTML有緩存機制,因此刷新的時候造成了bug,為了驗證對著這個猜測,我給寫入的flash字符串中添加了一個時間戳來“刷新緩存”,BUG依然存在,排除了這個緩存猜測。
如果換作其他的動態寫入是否也有這個BUG呢?于是想到了document.write,在這個實例中,針對object和embed我做了單獨輸出,測試發現document.write寫入前后的flash節點改變跟innerHTML前后的改變是一致的,但刷新BUG沒有出現。難道這個BUG真的是innerHTML的內部實現造成的,如果真是這樣那麻煩就大了,總不能指望微軟現在來改IE6吧。

  六、只有google一下innerHTML的內部機制了
  首先google了一下innerHTML和externalInterface,想看看是否也有人遇到這個問題了。直接G到一篇SWFObject論壇上的一個討論,對于Geoff在這里提到了幾種造成externalInterface通信失敗的可能性,我的實例中都沒有出現,可是BUG依然存在。不過這則討論中的一個細節引起了我注意,Geoff說他們在開發中一直都在使用externalInterface和js通信,從來沒有出現過bug,我也仔細看了他給出的demo,這里是AS調Js的方法。難道innerHTM只對addCallBack有負作用,call是正常的?于是我又做了一個demo,這真是一個讓我很無語的結論,原來call方法真的是有效的。也就是說innerHTML只對addCallBack有刷新bug。隨后google到一個 flex寫的externalInterface通信的例子更讓我覺得無語。我把這個flex寫的swf文件保存到了本地,并調用了其中addCallBack注冊的方法,察看實例,“靈異事件”發生了,無論我怎么刷新頁面,此前的bug都沒有出現。一下讓我將懷疑對象從innerHTML轉移到了AS2中的externalInterface類本身。不過這里還有一個疑問就是為何只在IE6內核的多標簽瀏覽器下才有此BUG呢?個人覺得可能性較大的原因是AS2中的externalInterface類確實還不完善,對于多標簽瀏覽器中更復雜的window對象的兼容做得還不夠好。而flex中采用的externalInterface機制可能更完善了。

  下班回來從7:30到11:30,整整四個小時的Debug最終結論居然出是因為AS2的內部實現有bug,在SWFUpload官方更改自己AS內部實現前,看來暫時只有先采用曲線救國的方式了:

  一、之前所提到的實例生成時,直接打印出SWFUpload中getFlashHTML方法針對object和embed的不同輸出,然后將這兩段代碼分別針對不同瀏覽器做硬編碼輸出,切忌這兩段代碼不能共存。

  二、禁止掉SWFUpload中loadFlash,然后擴展一個方法,利用document.write在指定dom位置調用,動態寫入flash元素。目前項目中我已經這樣做了,比第一種方法的擴展性要高點。
娛樂休閑專區A 影視預告B 音樂咖啡C 英語階梯D 生活百科
網頁編程專區E AMPZF HTMLG CSSH JSI ASPJ PHPK JSPL MySQLM AJAX
Linux技術區 N 系統管理O 服務器架設P 網絡/硬件Q 編程序開發R 內核/嵌入
管理中心專區S 發布網址T 版主議事U 事務處理
陕西快乐10分玩法 广东快乐十分走势图彩经网 广西快十开奖结果今天 江苏快3购买 幸运快3 炒股的app有哪些 北京快乐8好不好买 江西多乐彩11选5开奖结果 北京快乐8开奖官网 用周易算彩票中了一等奖