新鮮出爐的jquery fileupload 插件


內容屬原創,轉載請注明出處

為什么做這個東東

項目中需要用到一個多附件上傳的控件,找了一圈沒找到中意的(唯一一個中意點的還不開源,費用比較高),這不,只得自己掄刀上了。

需求是什么

這么個上傳的東東,要做哪些事情呢?

必須要干的事情:

1. 不能太丑,可以很素。

    原生的input file實在和項目主體不太搭配,需要另外想辦法。

2. 需要支持上傳多個附件,比如后台有個字段叫做 影像資料,這個影像資料,也許就是一張正面照,也許,還有一堆的證件照,需要支持多個。

3. 需要一個頁面上支持多個這樣的控件,今天有個影像資料,明天可能就出來一個 資質證書,這不,就得倆了。

4. 需要能查列表,上傳、下載、刪除

最好有的內容:

5. 實時進度條

6. 圖片類型的附件可以預覽。

7. 可以限制上傳的附件類型。

8. 支持配置上傳單個或者多個

上面這些東西,一個一個來唄。

 

怎么開工

做這么個東東,至少要涉及到兩塊內容:

1. 前端展示

2. 后端處理

既然咱項目用了spring,用了jquery,那么,就從這兩玩意入手唄,於是,決定這樣干:

1. 前端自定義一個jquery插件

2. 后台基於springMVC和commons-fileupload-1.2.1.jar實現上傳的具體業務

閑話莫提,開始捉刀。

 

前端插件的那些事

jquery是個好東東,要搞個插件有非常具體的套路,直接往上面套就好了,關鍵在於,邏輯怎么實現?

以前的項目用的是flash的插件,如今既然不想再依賴flash,那么,就用form提交來搞吧,步驟變成了這樣子的:

1. 初始化時調用后台query接口,生成列表,列表上支持下載和刪除。

2. 初始化時生成一個類型為 file的input,並綁定一個change事件 callback

3. 在callback中,動態生成一個form和一個iframe,並且把原來的file移到新的form中,另外再生成一個file放到原來的位置。把該form扔到隊列

4. 如果當前沒有提交的任務存在,那么生成一個提交的任務。

提交的任務中又在干嘛呢?

主要有下面幾個事情要做:

1. 當前有沒有正在提交還沒提交成功的form?如果有,繼續下面的步驟,如果沒有,從隊列中拿一個未提交的form,提交,如果隊列空了,任務結束。

2. 當前提交的form的目的地(iframe)的內容有沒有發生改變(通過檢測某個具體的dom)?如果發生了改變,說明提交已經結束,進入結束的處理。如果沒發生改變,那么,取進度條吧。

  2.1 提交已經結束,看下,成功還是失敗?成功了,設置進度條,生成刪除按鈕,再從第一個步驟開始。失敗了,提示下上傳失敗。

  2.2 提交還未結束,調用接口取下進度吧,同時,過個500毫秒從第一個步驟開始再來一次。

嗯,前端所有的邏輯基本上都在這里了。

后端的那些事

既然用了commons-fileupload-1.2.1.jar,那么只要做如下事情:

1. 新增類UploadProgressListener實現ProgressListener接口,在該接口的實現類中,首先從url里根據規則解析出來uploadId參數,然后往session例如該uploadId對應的進度。

    session里存的是個map,key為uploadId,value為進度值。
2. 繼承 CommonsMultipartResolver 實現一個類xx.xx.xx.CommonsMultipartResolver,在該實現類中通過類似下面代碼注入進度條監聽:

      String encoding = determineEncoding(request);
      FileUpload fileUpload = prepareFileUpload(encoding);
      ProgressListener pListener = new UploadProgressListener(request);
      fileUpload.setProgressListener(pListener);
View Code

3. 在spring的配置文件中配置multipartResolver為上面步驟中新實現的類: 

<bean id="multipartResolver" class="xx.xx.xx.CommonsMultipartResolver" p:defaultEncoding="UTF-8" >

嗯,差不多就這樣了。只是,這里面有個比較大的坑

在 UploadProgressListener 這個類中拿到的request的parameter一直是空的。。要等這個步驟做完之后request的參數才有值,這樣,支持多個附件上傳的那個參數uploadId怎么樣都拿不到。。最后,幸好MVC支持在url里帶參數,於是上傳的url就變成了:

  @RequestMapping(value="/file/{uploadId}/upload.json")

這樣,可以通過規則在request中拿到getRequestURI()之后再解析出來uploadId的值

 

差不多可以收工了。

 

寫在題外的

用的時候,還要注意什么下面這么些東西:

1. 后台存儲附件需要這么張關系表,里面保存了 file_group_id,file_id,file_name,file_path,file_size 至少這么些數據。

2. 控件基於jquery 1.7.2,未測試其他版本

3. 配置控件 上傳、新增、刪除、下載以及獲取進度條的action時,注意需要相對工程的根目錄配置,前面不要帶 /
4. 控件的action需要返回json數據,需要注意如下內容:
  a. 新增返回的json為如下格式,至少需要返回fileId和fileGroupId字段:
  

{model_list:[{"file_group_id":"XXXXX","file_id":"XXXXXXX"}]}

  同時,注意返回時,需要設置返回數據的頭部信息為 HTML,java中為:

  

response.setContentType("text/html;charset=UTF-8");

b. 刪除時后台通過參數 file_id 接收要刪除的 文件編號,不拋異常則認為是刪除成功

c. 下載時后台通過參數 file_id 接收要下載的文件編號,返回文件流
d. 獲取文件列表時,后台通過url里的參數 fileGroupId查詢該組號下的所有附件,的返回json數據為:

{model_list:[{file_group_id:'XX',file_id:'XXX1',file_name:'XX文件',file_path:'test/test/XX文件_20140810010101.html',file_size:1001},{file_group_id:'XX',file_id:'XXX2',file_name:'XX文件',file_path:'test/test/XX文件_20140810010102.html',file_size:1001}]}

e. 獲取文件上傳進度,返回的格式為json格式:

{"percent":10}

注意,為了支持多個文件上傳讀取進度,每一個文件上傳時有一個唯一的 uploadId,獲取文件上傳進度需要根據該參數進行,提交時的參數名為 upload_id

下載

這個fileupload的前端插件的地址已經放在github上,路徑:

https://github.com/kevin82008/fileupload

效果圖:

水平所限,如有不對,歡迎拍磚。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM