SWFUpload學習記錄

  最近項目中要求使用HTTP作文件上傳,並且要求有進度顯示,在網上東找西尋了半天,解決方案倒也很多,好比使用Ajax上傳,但感受這種方式的進度提示 太麻煩,因此沒有采用,後來看到了SWFUpload,就找了些資料來看,以爲符合本身的要求,研究了足有兩天,略有心得,忙不迭地記錄下來,以防止時間 長了遺忘,若是不當心幫助了別人,那就更好了,呵呵...javascript

下面摘抄一段SWFUpload官網的介紹(別人翻譯過來的):css

SWFUpload 最初是由Vinterwebb.se 開發的客戶端文件上傳工具。它結合javascript和flash在瀏覽器中提供一個優於傳統上傳標籤 <input type="file" /> 的功能(和良好的用戶體驗)。html

SWFUpload 的主要特性:java

 

  • 文件瀏覽對話框中能夠選擇多個文件
  • AJAX風格的上傳,不用重刷新
  • 上傳過程當中的各類事件.
  • 能夠在客戶端調節圖片大小
  • 它使用的類命名空間兼容各類js庫(i.e., jQuery, Prototype, 等.).
  • 支持 Flash 9 and Flash 10 (2.2.0版本後取消對flash 8的支持)

 

 

SWFUpload 的設計理念與其餘基於flash的上傳工具不一樣。SWFUpload 給開發者儘量多的UI控制能力. 開發者可使用 XHTML, CSS, JavaScript 來使它更符合本身網站的樣式風格. 它提供一組簡單的js事件更新上傳狀態,開發者能夠根據這些事件來在網頁中顯示文件上傳進度
jquery

好了,誇獎的話很少說了,既然它這麼受歡迎,想必是有必定優點的。web

下面記錄一下我作的一個小示例,先預覽一下程序運行效果:瀏覽器

SWFUpload文件上傳效果圖

有朋友索要例子源碼,其實我早已放在個人資源裏了,並無設置下載積分,有須要的朋友請到這裏下載:http://download.csdn.net/detail/zhangyihui1986/4538748服務器

 

準備工做

 

如今SWFUpload項目託管於Google code下,URL爲:http://code.google.com/p/swfupload/  ,請自行下載,下載的壓縮文件中含有一個文檔,裏面詳細介紹了SWFUpload的配置參數、事件支持、支持方法等。cookie

這裏是官網上的幾個例子:http://demo.swfupload.org/網絡

網絡上關於SWFUpload的博客資源不少,但不少博客質量不過高,並且轉來轉去,內容重複,因此我在查資料的時候沒有找到太合適的資源,後來找到了這裏:http://webdeveloperplus.com/jquery/multiple-file-upload-with-progress-bar-using-jquery/ ,這是一個外國人寫的關於SWFUpload的小教程,UI作地也挺好,因而我就參照着作了個小例子。

不過,上面連接的教程是針對SWFUpload一個針對JQuery的插件寫的,這個插件地址爲:http://blogs.bigfish.tv/adam/2009/06/14/swfupload-jquery-plugin/,該插件好像僅僅是完善了一下SWFUpload的事件機制,使用它可採用JQuery的鏈式寫法,但我沒有用它,而是用的原生的SWFUpload2.2版本。

 

示例實現步驟

 

很少說,先貼出來我作的例子,而後再針對代碼做適當解釋。

例子使用了Struts2.3.4做爲後臺,固然,SWFUpload是不選擇後臺的,您可使用任意的技術,只要是能實現HTTP協議便可。

1)將下載的壓縮文件解壓並拷到web項目中(此處我放到項目的js目錄下),創建其它資源(如JSP、Action等)後目錄結構以下圖所示:

項目結構

2)在JSP文件中引入SWFUpload依賴的JS文件

 

[html]  view plain copy
 
  1. <link== = /> <script= =></script> <script= =></script> <script= =></script> <script= =></script> <script= =></script> <script= =></script>  

在此處我用到了ligerUI框架,若是不使用它,那麼僅須要引jquery和swfupload.js兩個文件便可。

3)JSP文件中HTML結構

 

[html]  view plain copy
 
  1. <div=> <span=></span> <p=></p> <ol=></ol> </div>  


4)JSP文件中CSS,給文件上傳進度列表賦與樣式,我對CSS不夠熟悉,此處的樣式幾乎所有來自於前面那個教程,僅做了一些小的變更。若是您以爲這還不夠好,那您本身來實現漂亮的UI界面吧!

 

 

[css]  view plain copy
 
  1. #logLismarginpaddingwidth }    
  2. #logLislist-style-positionmarginborder  paddingcolor;  
  3. font-sizebackgroundposition; }    
  4. #logLisborder1px height5pxbackground#fff #logLiscolormargin-left }      
  5. #logLisbackground#999width0%height5px #logLismargin0line-height18px #logLisborder1px background#ccf9b9 #logLisbackgroundurl'../images/delete.gif'positionabsolute;  
  6. width16pxheight16pxcursorpointer }    


5)JSP中的Javascript,主要是建立SWFUpload組件實例,並綁定監聽函數,在監聽函數中處理進度提示:

 

 

[javascript]  view plain copy
 
  1. var var function ).val();  
  2. varnew ,  
  3. ,  
  4. ,  
  5. true ,  
  6. ,)  
  7. ,  
  8. ,  
  9. //      file_upload_limit: 5,   
  10. ,  
  11. ,  
  12. ,  
  13. false //========================================  回調函數Handlers  =================================== /** 
  14. * 打開文件選擇對話框時響應 
  15. */ function if null /** 
  16. * 文件被加入上傳隊列時的回調函數,增長文件信息到列表並自動開始上傳.<br /> 
  17. * <p></p> 
  18. * SWFUpload.startUpload(file_id)方法致使指定文件開始上傳, 
  19. * 若是參數爲空,則默認上傳隊列第一個文件;<br /> 
  20. * SWFUpload.cancelUpload(file_id,trigger_error_event)取消指定文件上傳並從隊列刪除, 
  21. * 若是file_id爲空,則刪除隊列第一個文件,trigger_error_event表示是否觸發uploadError事件. 
  22. * @param file 加入隊列的文件 
  23. */ function varthis var;  
  24.  + file.name +  + Math.round(file.size/1024) + ;  
  25. ;  
  26. ).append(listItem);  
  27.  + file.id + function  + file.id).slideUp();  
  28. //  swfUpload.startUpload(); /** 
  29. * 文件加入上傳隊列失敗時觸發,觸發緣由包括:<br /> 
  30. * 文件大小超出限制<br /> 
  31. * 文件類型不符合<br /> 
  32. * 上傳隊列數量限制超出等. 
  33. * @param file 當前文件 
  34. * @param errorCode 錯誤代碼(參考SWFUpload.QUEUE_ERROR常量) 
  35. * @param message 錯誤信息 
  36. */ function if );  
  37. return if var   
  38. switch case ;  
  39. break case ;  
  40. break case ;  
  41. break default );  
  42. break /** 
  43. * 選擇文件對話框關閉時觸發,報告所選文件個數、加入上傳隊列文件數及上傳隊列文件總數 
  44. * @param numSelected 選擇的文件數目 
  45. * @param numQueued 加入隊列的文件數目 
  46. * @param numTotalInQueued 上傳文件隊列中文件總數 
  47. */ function varthis if var);  
  48. forvarin var);  
  49. var + queueErrorArray[i].file.name +    
  50.  + queueErrorArray[i].file.size + ;  
  51. ,  
  52. ,  
  53. function ).text( + numSelected   
  54.  + numQueued);  
  55. else this /** 
  56. * 文件開始上傳時觸發 
  57. * @param file 開始上傳目標文件 
  58. */ function if ).text();  
  59. ).text();  
  60. /** 
  61. * 文件上傳過程當中定時觸發,更新進度顯示 
  62. * @param file 上傳的文件 
  63. * @param bytesCompleted 已上傳大小 
  64. * @param bytesTotal 文件總大小 
  65. */ function var ).css(,percentage + );  
  66. ).text(percentage + );  
  67. /** 
  68. * 文件上傳完畢而且服務器返回200狀態碼時觸發,此時文件的上傳週期並未完成, 
  69. * 不能在此事件監聽函數開始下一個文件的上傳 
  70. * @param file 上傳的文件 
  71. * @param serverData 服務器在執行完接收文件方法後返回的數據 
  72. * @param response Boolean類型,表示是否服務器返回數據 
  73. */ function var ).css(,);  
  74. ).css(,).text();  
  75. ).find().html();  
  76. /** 
  77. * 在一個上傳週期結束後觸發(uploadError及uploadSuccess均觸發) 
  78. * 在此能夠開始下一個文件上傳(經過上傳組件的uploadStart()方法) 
  79. * @param file 上傳完成的文件對象 
  80. */ function this }  


代碼解釋


1)SWFUpload組件的實例化

SWFUpload組件的實例化很簡單,就是new一個JS對象,如

[javascript]  view plain copy
 
  1. varnew SWFUpload({settings});  

咱們須要傳給它一個配置對象,這個配置對象的內容不少,詳細介紹請參照使用說明文檔,在此僅介紹幾個重要一些的配置參數,以註釋的形式寫在代碼裏。

 

 

[javascript]  view plain copy
 
  1. upload_url: ,       
  2. ,        
  3.   
  4.   
  5.   
  6. ,          
  7.   
  8. ,     
  9.   
  10.   
  11.   
  12.   


須要注意的是按鈕的高和寬必定要指定,不然flash沒法顯示。


2)添加事件監聽器

        swfupload僅實現了後臺操做,前臺的處理空間留給了開發者,它採用事件觸發機制,讓開發者捕獲特定事件,自定義對應的事件處理函數進行相應處理。 即當swfupload內部某一特定事件發生,便觸發相應的JS函數,並傳入合適的相關參數,開發者就能夠拿着這些參數來更新UI界面以提示上傳進度了。 Swfupload經過固定的事件函數名屬性值尋找自定義的JS函數,因此在初始化工做中,將自定義的JS函數名賦值給swfupload指定的對應屬性 便可。

[javascript]  view plain copy
 
  1. // handlers:事件監聽函數,請參考使用說明文檔   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   

3)開始文件上傳

        默認狀況下,你選擇了文件並關閉了文件選擇對話框文件並不會自動開始上傳,你須要調用SWFUpload的startUpload()方法,該方法接收一個file_id做爲參數,若是參數爲空,則自動開始上傳文件隊列中的第一個文件。

另外,在全部的事件監聽器中,this關鍵字都是指向SWFUpload對象,因此你能夠在file_queued_handler或file_dialog_complete_handler等事件監聽器中這樣開始文件上傳:

[javascript]  view plain copy
 
  1. this.startUpload();  

4)批量文件上傳

        默認狀況下,你在第3步中開始了一個文件上傳,可是若是你選擇的是多個文件,那麼你會發現這個文件上傳後其它文件並不會自動開始上傳,這是爲何呢?原來 Swfupload雖支持批量上傳,但本質還是單個文件依次上傳,因此若是你的上傳是支持多個文件上傳那只有你本身去開始其它文件的自動上傳了,咱們能夠 在upload_complete_handler事件監聽器中再調用一個startUpload()方法:

[javascript]  view plain copy
 
  1. this.startUpload();  

由於upload_complete_handler事件是在一個文件上傳後觸發,無論該文件是否上傳成功都會觸發該事件,因此咱們在這裏再調用一次startUpload方法是合適的,這樣SWFUpload組件在前一個文件上傳完成後就會自動開始下一個文件的上傳。


5)顯示上傳文件進度列表

        顯示出上傳文件進度列表可以加強用戶體驗,由於用戶將看見選擇的文件信息以及該文件的上傳進度,這些東西就徹底由開者來定製了,SWFUpload組件將 豐富的文件信息及上傳進度在調用事件監聽函數時以參數的形式傳進來,咱們就能夠利用這些信息動態更新文件上傳進度UI了。如前面的例子咱們在 file_queued_handler事件監聽函數中將文件信息及其進度條拼接到頁面的ol列表中,在upload_start_handler事件監 聽函數中初始化進度條顯示,而後在文件上傳過程當中會不停地觸發upload_progress_handler事件,咱們就在這個事件監聽函數中獲取上傳 進度,並將其更新到進度列表,這樣即可實現文件上傳的進度提示。在SWFUpload豐富的事件機制支持下,實現這些東西是很容易的事。


6)有關中文傳遞

在SWFUpload的配置參數中有一個post_params參數是用來向後臺傳遞參數的,默認狀況好像是不能傳遞參數的,可是若是你將另外一個配置參數use_query_string設置爲true以後就能夠傳遞參數了。

該參數接收一個JS對象,相似於這樣:

[javascript]  view plain copy
 
  1. use_query_string: true ,  
  2.   
  3. }  

可是若是參數值中含有中文的話,那麼後臺會報錯,也取不到值,能夠這樣解決:

在JS中先用UTF-8進行中文編碼

[javascript]  view plain copy
 
  1. use_query_string: true ,)  
  2. }  

而後在後臺再轉回來,在Java中就體現爲

[java]  view plain copy
 
  1. URLDecoder.decode(request.getParameter(), );  

如此即可解決中文參數傳遞問題。


7)有關頁面跳轉

        假設有這種需求:文件上傳完成後跳轉到指定的頁面,好比文件信息查看頁面,那咱們可能會一時找不到好的方法,由於SWFUpload上傳相似於Ajax上 傳,涉及到的上傳交互操做並不是是瀏覽器所發,而是由Flash發出的上傳請求,那麼後臺給出的跳轉信息瀏覽器天然接收不到,而是由Flash接收到了,既 然瀏覽器接收不到跳轉信息,那麼自動跳轉就不會發生。

對於這種需求,咱們能夠參照Ajax提交跳轉的方式,在後臺成功接收文件後輸出一些信息,好比跳轉的頁面,或者僅僅是一個字符串,而把跳轉的任務交由 Javascript來完成,那麼咱們應該在什麼事件監聽函數中處理呢!您能夠看看upload_success_handler這個事件的回調函數有什 麼參數,以下:

[javascript]  view plain copy
 
  1. uploadSuccess(file object, server data, received response)  

        這個事件發生後會傳三個參數到咱們定義的監聽函數中,第一個是上傳完成的文件對象(關於文件對象可參看SWFUpload的文檔,其實就是一個JS對象, 包含一些重要的文件信息),第二個實際上是服務器返回的數據,若是後臺用的直接跳轉,那麼這裏的server data就會是跳轉頁面的HTML結構,document.write()將其輸出,也算是完成跳轉了吧!若是你僅僅是向前臺輸出個字符串,並無跳轉, 那麼這裏就應該是你輸出的字符串,在這裏就能夠用location.href=「來實現跳轉;第三個參數是Boolean類型,表示是否接收到服務器傳回 的數據。

        須要注意的是該事件在每一個文件上傳成功均會觸發,若是同時在上傳多個文件,那麼第一個文件上傳完成後頁面就直接跳轉了,後臺的文件也就得不到機會上傳了, 因此這裏須要判斷一下隊列裏是否還有沒有上傳完成的文件,若是沒有了再跳轉,就能夠了,至於如何判斷隊列裏是否還有未上傳的文件,這裏用到了 SWFUpload的另外一個對象Stats。該對象提供了上傳隊列的狀態信息,訪問實例的getStats方法可獲取此對象,該對象中有一些屬性,其中有 一個files_queued屬性能夠表示是否還有未上傳的文件,若是該屬性爲0則表示所有上傳,能夠這樣作

[javascript]  view plain copy
 
  1. ifthis   
  2. }  

8)有關SWFUpload組件在非IE瀏覽器中不傳遞Cookie的問題

        最近在使用SWFUpload過程當中發現一個問題,文件上傳成功後我須要將其移動到指定目錄下,因爲目錄信息是在Session中的,這時在非IE瀏覽器 中出現了問題,Session中沒有東西,用戶登陸信息也沒有了。通過調試才發現文件上傳成功後在後臺取到的Session與用戶登陸完成後的 Session相比根本就不是一個Session了,它們的ID不一樣,也就是說文件上傳另生成了一個Session,而這個Session是全新的,固然 沒有了登陸時存放的信息了。

        通過一番搜索,這是因爲Flash Player在非IE瀏覽器下一個Bug引發的,這裏有一段描述:

Cookie issue

On Windows the Non-IE Flash Player plugin (FireFox, Opera, Safari, etc) sends the IE cookies regardless of the browser used. This breaks authentication and sessions for many server-side scripting technologies.

Developers should manually pass Session and Authentication cookie information and manually restore Sessions on the Server Side if they wish to use Sessions

The SWFUpload package contains work-around sample code for PHP and ASP.Net

        也就是說非IE瀏覽器下Flash Player插件發送的也是IE瀏覽器當前頁面的cookie,而且Session是靠Cookie中保存的SessionId實現的,所以後臺處理程序另新建了Session,程序也就出現了上述錯誤。

        找到的解決辦法是手動將SessionID傳到後臺服務端。

        在上傳路徑URL里加上jsessionid變量便可,以下:

[javascript]  view plain copy
 
  1. upload_url: contextPath +   

         這樣就能夠解決問題了,有人還說可使用SWFUpload組件的一個插件:swfupload.cookies.js,但我沒有弄好,看它的源碼是分 析瀏覽器的cookie而後將它們拼接到post_params配置項中,我手動拼上jsessionid也是不起做用,不知道是否是本身沒弄對,反正是 這個插件我沒有成功使用。

 

 

 http://www.wonima.com正在舉行投稿發帖送iphone、以及現金活動,絕對新鮮

相關文章
相關標籤/搜索