程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> chunkupload 文件上傳斷點續傳組件(java),uploadify斷點續傳

chunkupload 文件上傳斷點續傳組件(java),uploadify斷點續傳

編輯:JAVA綜合教程

chunkupload 文件上傳斷點續傳組件(java),uploadify斷點續傳


 chunkupload簡介

     

     chunkupload是一款基於java語言的斷點續傳組件,針對文件上傳,非文件下載,集成方便,使用簡單。

     chunkupload實現如下功能:

 

     ·  實現斷點續傳

     ·  對於同一個文件,允許多用戶同時上傳,並且上傳的用戶越多,上傳越快

     ·  線程安全

     ·  同一物理機下進程安全

     ·  文件自動切片,支持合並

     ·  內存占用小

     ·  高效穩定,高可用

     ·  易集成,無第三方依賴

 

     chunkupload只關注文件上傳,並沒有安全機制,開發者需要自行設計安全控制策略,防范用戶上傳非法文件,chunkupload默認上傳的文件是安全的。

     chunkupload功能完備,服務端和客戶端無縫銜接,開發者只需關注自身業務和UI展現即可。

     為了盡可能提升用戶體驗,chunkupload在客戶端的技術選型有些激進,采用了許多先進的技術,比如:web worker、XMLHttpRequest數據傳送進度、FileReader、file slice等,所以對浏覽器兼容性會有一定影響,在確定使用chunkupload前請務必仔細斟酌!

 

chunkupload集成

 

服務端

 

     chunkupload服務端運行需要JRE7或更高版本,無任何第三方依賴。

 

     1.引用chunkupload.1.0.jar

     2.在項目web.xml中配置chunkupload servlet

 

1 <servlet>
2     <servlet-name>ChunkUpload</servlet-name>
3     <servlet-class>com.iyangyuan.chunkupload.servlet.DispatcherServlet</servlet-class>
4 </servlet>
5 <servlet-mapping>
6     <servlet-name>ChunkUpload</servlet-name>
7     <url-pattern>/chunkupload/*</url-pattern>
8 </servlet-mapping>

 

     強烈建議將chunkupload servlet配置在安全框架之後(比如shiro),mvc框架之前(如springmvc)。

     chunkupload servlet中的攔截路徑(url-pattern),如果無特殊需求,無需更改,假如一定要更改,還需要同步更改客戶端的配置。

 

 客戶端

 

     chunkupload客戶端對浏覽器的要求比較高,目前已知chrome、firefox浏覽器完整支持,360浏覽器如果啟用webkit內核,應該也沒有問題,IE浏覽器絕對不支持(想都不要想),其他浏覽器未知。

     開發者可能會問,為什麼兼容性如此捉襟見肘?

     chunkupload是新時代的產物,它代表了時代的發展方向,它的價值在於提供最先進的技術示范,而不是沉重的歷史包袱。

     chunkupload在客戶端的實現,無任何第三方依賴,只關注與服務端的邏輯交互,並不干預UI展現,為開發者創造最大的發揮空間。

 

     1.引用dawn.1.0.js,用於在客戶端計算文件MD5,dawn.js是chunkupload的一個附屬項目,相比未經優化的javascript計算MD5方法,dawn.js將計算效率提升50%左右。

     2.引用chunkupload.1.0.js,此乃chunkupload客戶端核心庫,封裝了所有上傳所需的邏輯。

 

 chunkupload使用

 

服務端

 

     服務端需要創建chunkupload.properties配置文件,放置在項目classpath根目錄下,也就是大家熟悉的log4j.properties所在目錄,配置文件中有如下選項:

 

     ·  root 文件存儲路徑,相當於根目錄,內部還會有chunkupload創建的目錄結構;假如同一台物理機配置多個文件上傳容器,此項配置應該設置成統一目錄,默認為[/data]。

     ·  fileLockCapacity 文件鎖緩存容量,一般設置為2048即可,開發者可根據服務器性能自行調整,默認為2048。

     ·  createFile 文件上傳完成後,是否立即合並切片,生成完整文件;強烈建議此配置項設置為false,一般情況下,切片無需合並,就算合並,也不需要立即合並;如果設為true,立即合並文件會占用大量服務器資源,並且會造成客戶端長時間等待;合並的速度大約100M/S,視服務器具體性能而定,默認為true。

 

     至此,服務端已經可以正常運作了。

 

客戶端

 

     默認情況下,客戶端無需任何配置。

     假如開發者更改過chunkupload servlet攔截路徑,那麼chunkupload.1.0.js中的Block.config.api配置也需要做相應的改動,具體情況需要開發者自行斟酌。

 

     ChunkUpload 類

 

     文件上傳核心實現類。

 

          實例化

 

          上傳組件初始化需要提供目標文件。

 

1 /**
2 
3  * 實例化ChunkUpload組件
4 
5  * file 要上傳的目標文件對象
6 
7  */
8 
9 var cu = new ChunkUpload(file);

 

          upload 方法

 

          upload 方法用來啟動文件上傳,通過四個異步回調完成上傳交互,無返回值。

 

 1 cu.upload({
 2     "success": function(block){
 3         /**
 4          * 上傳成功回調
 5          *
 6          * block 對象,塊對象
 7          */        
 8     },
 9     "error": function(e){
10         /**
11          * 上傳異常回調
12          *
13          * e 字符串,異常信息
14          */
15     },
16     "md5Progress": function(n){
17         /**
18          * 計算文件md5進度回調
19          *
20          * n 整型,進度數值
21          */
22     },
23     "uploadProgress": function(n){
24         /**
25          * 上傳進度回調
26          *
27          * n 整型,進度數值
28          */
29     }
30 });

 

          abort方法

 

          abort方法用來中斷上傳,可以在任意階段任意時刻中斷,無返回值。

 

1 cu.abort();

 

     Block 類

 

     文件控制類。

 

          實例化

 

 1 /**
 2 
 3  * 初始化塊對象
 4 
 5  * md5 文件md5,32位
 6 
 7  * size 文件大小,字節
 8 
 9  */
10 
11 var block = new Block(md5, size);

 

          info方法

 

          獲取塊(文件)信息,返回javascript對象。

 

1 block.info();

 

          返回示例:

 

 1 {
 2 
 3     "status": 0,   //業務狀態,0表示成功
 4 
 5     "data": {  //數據域
 6 
 7         "chunks": [  //所有切片信息
 8 
 9             {
10 
11                 "md5": "e114c21f7d9f8ad1a8551225c3d085be",   //切片md5
12 
13                 "n": 1  //切片序號
14 
15             },
16 
17             {
18 
19                 "md5": "48357caa7607a636e858315e1b0216d5",
20 
21                 "n": 2
22 
23             },
24 
25             {
26 
27                 "md5": "a23c6ab7104d2ce4ae3c1624ea7eab55",
28 
29                 "n": 3
30 
31             },
32 
33             {
34 
35                 "md5": "3eb29f6241d6fbb35cc715fff2b9ab91",
36 
37                 "n": 4
38 
39             },
40 
41             {
42 
43                 "md5": "120ddc96b878a63adcd7835cbac0c95c",
44 
45                 "n": 5
46 
47             }
48 
49         ],
50 
51         "chunkNum": 5,   //切片數量
52 
53         "md5": "f1154ca6fab7f3628927c1268f3570fd",   //文件md5
54 
55         "state": 1,   //文件狀態,1為上傳完成
56 
57         "size": 20879935  //文件長度
58 
59     }
60 
61 }

 

          delete方法

 

          刪除塊(文件) ,無返回值。

 

1 block.delete();

 

chunkupload服務端存儲珠玑

 

     任何上傳的文件都會在服務端進行切片處理,每個切片4M大小。

     通過文件MD5和文件大小,唯一確定一個文件。

     目錄分散策略,基於開發者自定義的rootpath,文件MD5前6位,每兩位作為一級目錄,最後以文件MD5+文件長度作為最終目錄,所有文件信息均存儲在此目錄下。

     假如文件MD5為[071287fffa974b878732a7a17858be36],長度為[20879935],開發者自定義的rootpath[/data],那麼生成的目錄結構為:[/data/07/12/87/071287fffa974b878732a7a17858be3620879935]。

     chunkupload存儲的關於文件的所有信息,均為二進制文件,並且文件名稱固定,具體組織如下圖:

 chunkupload未來

 

     展望chunkupload,未來無疑是開源的,只不過現在還不是時候,因為作者覺得它還不夠完美。

     通過大家的寶貴意見、建議,作者會不斷完善、改進chunkupload,等到chunkupload成熟時,也就是開源之日!

     希望大家多多與我交流~

 

chunkupload組件下載

 

     你可以下載如下內容:

 

     · chunkupload.jar

     · chunkupload.js

     · dawn.js

     · 腳手架(集成了chunkupload的空白項目)

 

下載

 

附:客戶端使用示例

 

 上傳示例

 

1 <html> 2 <head> 3 <title>ChunkUpload 文件上傳示例</title> 4 <meta charset="utf-8"> 5 <meta name="viewport" id="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"> 6 <style> 7 body{ 8 font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 9 } 10 body > div { 11 width: 200px; 12 margin: 20px auto 0 auto; 13 } 14 body > div.form { 15 text-align: center; 16 } 17 body > div.form > input { 18 margin-top: 12px; 19 border: 1px dashed #dcdcdc; 20 padding: 4px 8px; 21 cursor: pointer; 22 background-color: transparent; 23 color: #686868; 24 font-family: inherit; 25 outline: none; 26 width: 100%; 27 box-sizing: border-box; 28 } 29 body > div.form > input.button { 30 font-size: 15px; 31 line-height: 29px; 32 padding: 0 10px; 33 } 34 body > div.form > input:hover { 35 background-color: #f5f5f5; 36 } 37 div.info > div{ 38 margin: auto; 39 height: 31px; 40 width: 88px; 41 background: url('data:image/gif;base64,R0lGODlhWAAfAMMBAAAAAP////XcoPDLdfTboP+dzv+z2f+AwP9brfPZoAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFFAAKACwAAAAAWAAfAAAE/xDISau9OOvNd/hgKI5kaZ5oWkqB4L5wLM90bd+4PLB57//A2g7QChqPyNiwmGw6c8undKrj/STULC3qAxQAMKw0IUiYyy6yWf3j5rwGsMsrd5JfdzQelre5bxIFcROCdUBneWx6aHd9UFY1hAaTAJQTRo6LfYl8i0KQMoGCk6Slg0FsnGmdq3uZSpBiAnCmtaWGqK4yiq2eVURzwbS2pBK3hzabezOvLlxyYMPEg5aXWk1uWNLTxaOU10lR2oHckwcHlIWn4Ed/c97ECOfocJWy7EDus/C28udx8HAlaZYP1ItttRAgKEYBGS9NelL10LevnC2BR1RhM3iwAD9uGE5/NBvpg+IcLx5BhvTxiiDBGSYPivJI0xo+JzHfZfjyxNHDGC9/MaFhb0bRmzg5hoqE9EnOpk2XDJhKtarVq1izat3KtSvWDmDDih0LNgIAIfkEBRQACgAsAwAGADEAFgAABJ9QyEmrBMDqzbsFRTZh3pacZQUaogC2qZRQc4oVLLbCaS2XOpyBNdTxYjPf5iYcOp+kmCfqaj6vUClHlFlhr5is9nOpfsGAonGs6lrPUOvR1r3BnYdDEZemskdvWAh5ejs5fyqBV4N5LHKIiXcGCAhORnMmAkoUXpJgkEsFimeYPVsgond+oEtMoq86rJpTIZdBpbIjLBp9spu8W7nCshEAIfkEBRQACgAsAwAFADoAFgAABLdQyEmrAMDqzWXySdhZQJFN2KhS30oWxnmZrtp++IrB2B7XNmAPZogVezKgJidobXbEonSaUjaZE2erOpt6vz+gk5VFSTIlsBdDFTffnRM6qo4Bjkirbl4Hp6VJHTdxaD59BgcHRzx2ei5/dQiJiml3XI5xdGCSiTF0gZhPml8ICIB5oSqQh22pjwWjdaAuOWNjJCWwfZeuWoS5sME9rh4VtxolSMo0vXqWyGHESyOzZ9LHx9LaAhEAIfkEBRQACgAsAgAFAEQAFgAABMtQyEmrvTjrmmT63VYBgGieVIhSQFFO5CpPYWefrfEK7T5fto+g9iMVdKSc75dqOlWZ5NGgoyaXK6HqNvR4vxbjlEoux2ZQcHrL2uXK8DhWdGODo5LSO24GmJlqXSIvemN8Vn5ISVkaaRgxe4dwkXOAGpBGkmQHB1ZHfmeWRYZ8CJydSkiiTJGlpzqGlauDpHEICGRXsrMbrZq5THVPXcJhBbWSu2g0MmLIucona4BSx9YuoaKOzBbbMNi6RtHaRToXoLyO3nfneLw/EQAh+QQFFAAKACwCAAUASwAXAAAE3lDISau9OOtdE/9gKI4aAJDo5qUSUJyTyVJeYgtrfeesa8ACF5C1khSLuEkNZSr8TL4haKdMWpM8o/YDdRp+X6iUg9xer2VR0/ttu2Wh5bFKP5eAPrd+P55W00t2FjAneXtvAG9xGkhzHIRBbIdhiU9QM5gxhZKTb5J9mSAyXZ1tBwdhTolwoZiGkwinqFFPrZmvh7GnP5+haTSinHsICG1ioBdywFo8WRu4pcaZjslqBcKdyGQYv2ZcLtelrCS/3YKia9fql7btgy/HXdofZYHVTD8Xq+78FMjz/TBEAAA7') no-repeat center center; 42 padding: 2px; 43 box-sizing: border-box; 44 } 45 div.info > div > p{ 46 text-align: right; 47 font-size: 12px; 48 margin: 0; 49 } 50 </style> 51 </head> 52 <body> 53 <!-- 表單部分 --> 54 <div class="form"> 55 <input id="bigFile" type="file" placeholder="選擇一個文件" /> 56 <input id="execBtn" class="button" type="button" value="上傳" /> 57 <input id="cancelBtn" class="button" type="button" value="取消" /> 58 </div> 59 <!-- 上傳進度展示 --> 60 <div class="info"> 61 <div> 62 <!-- 提示文本 --> 63 <p id="text"></p> 64 <!-- 執行進度 --> 65 <p id="progress"></p> 66 </div> 67 </div> 68 </body> 69 <script src="/static/lib/dawn/dawn.js"></script> 70 <script src="/static/lib/chunkupload/chunkupload.js"></script> 71 <script> 72 var fileInput = document.getElementById("bigFile"), 73 execBtn = document.getElementById("execBtn"), 74 cancelBtn = document.getElementById("cancelBtn"), 75 text = document.getElementById("text"), 76 progress = document.getElementById("progress"), 77 cu; 78 79 execBtn.addEventListener("click", function(e) { 80 var file; 81 file = fileInput.files[0]; 82 cu = new ChunkUpload(file); 83 cu.upload({ 84 "success": function(block){ 85 /** 86 * 上傳成功後,會返回一個block對象 87 * 通過block對象,可以在一定程度上管理文件,目前支持: 88 * 獲取文件信息(參見info_example.html) 89 * 刪除文件(參見delete_example.html) 90 */ 91 text.innerText = "上傳完成"; 92 }, 93 "error": function(e){ 94 text.innerText = e; 95 progress.innerText = ""; 96 }, 97 "md5Progress": function(n){ 98 text.innerText = "計算MD5"; 99 progress.innerText = n + "%"; 100 }, 101 "uploadProgress": function(n){ 102 text.innerText = "正在上傳"; 103 progress.innerText = n + "%"; 104 } 105 }); 106 }); 107 108 cancelBtn.addEventListener("click", function(e) { 109 if(cu){ 110 cu.abort(); 111 alert("已經取消!"); 112 } 113 }); 114 </script> 115 </html> View Code

 

獲取文件信息示例

 

1 <html> 2 <head> 3 <title>ChunkUpload 獲取文件信息示例</title> 4 <meta charset="utf-8"> 5 <meta name="viewport" id="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"> 6 <style> 7 body { 8 font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 9 } 10 body > div { 11 width: 200px; 12 margin: 20px auto 0 auto; 13 } 14 body > div.form { 15 color: #686868; 16 font-size: 15px; 17 text-align: center; 18 } 19 body > div.form > p { 20 margin: 1em 0 .4em 0; 21 text-align: left; 22 } 23 body > div.form > input { 24 background-color: transparent; 25 outline: none; 26 font-family: inherit; 27 font-size: inherit; 28 color: inherit; 29 } 30 body > div.form > input:hover { 31 background-color: #f5f5f5; 32 } 33 body > div.form > input.text { 34 padding: 6px 8px; 35 border: 1px solid #dcdcdc; 36 } 37 body > div.form > input.button { 38 border: 1px dashed #dcdcdc; 39 cursor: pointer; 40 padding: 0 10px; 41 line-height: 29px; 42 } 43 div.info{ 44 width: 400px; 45 background-color: #f7faff; 46 border: 1px solid #b2d7ff; 47 padding: 10px 8px; 48 } 49 div.info > p{ 50 margin: 0; 51 text-align: left; 52 font-size: 14px; 53 word-break: break-all; 54 } 55 </style> 56 </head> 57 <body> 58 <!-- 表單部分 --> 59 <div class="form"> 60 <p>文件md5</p> 61 <input id="md5" class="text" type="text" placeholder="文件md5" /> 62 <p>文件大小(字節)</p> 63 <input id="size" class="text" type="text" placeholder="文件大小(字節)" /> 64 <p></p> 65 <input id="execBtn" class="button" type="button" value="獲取" /> 66 </div> 67 <!-- 結果展示 --> 68 <div class="info"> 69 <p id="text"> 70 </p> 71 </div> 72 </body> 73 <script src="/static/lib/dawn/dawn.js"></script> 74 <script src="/static/lib/chunkupload/chunkupload.js"></script> 75 <script> 76 var execBtn = document.getElementById("execBtn"), 77 md5 = document.getElementById("md5"), 78 size = document.getElementById("size"), 79 text = document.getElementById("text"); 80 81 execBtn.addEventListener("click", function(e) { 82 var block = new Block(md5.value, size.value); 83 84 block.info(function(info){ 85 text.innerText = JSON.stringify(info); 86 },function(status, text){ 87 text.innerText = "哎呀!出錯啦," + text; 88 }); 89 }); 90 </script> 91 </html> View Code

 

刪除文件示例

 

1 <html> 2 <head> 3 <title>ChunkUpload 刪除文件示例</title> 4 <meta charset="utf-8"> 5 <meta name="viewport" id="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"> 6 <style> 7 body { 8 font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; 9 } 10 body > div { 11 width: 200px; 12 margin: 20px auto 0 auto; 13 } 14 body > div.form { 15 color: #686868; 16 font-size: 15px; 17 text-align: center; 18 } 19 body > div.form > p { 20 margin: 1em 0 .4em 0; 21 text-align: left; 22 } 23 body > div.form > input { 24 background-color: transparent; 25 outline: none; 26 font-family: inherit; 27 font-size: inherit; 28 color: inherit; 29 } 30 body > div.form > input:hover { 31 background-color: #f5f5f5; 32 } 33 body > div.form > input.text { 34 padding: 6px 8px; 35 border: 1px solid #dcdcdc; 36 } 37 body > div.form > input.button { 38 border: 1px dashed #dcdcdc; 39 cursor: pointer; 40 padding: 0 10px; 41 line-height: 29px; 42 } 43 div.info{ 44 width: 400px; 45 background-color: #f7faff; 46 border: 1px solid #b2d7ff; 47 padding: 10px 8px; 48 } 49 div.info > p{ 50 margin: 0; 51 text-align: left; 52 font-size: 14px; 53 word-break: break-all; 54 } 55 </style> 56 </head> 57 <body> 58 <!-- 表單部分 --> 59 <div class="form"> 60 <p>文件md5</p> 61 <input id="md5" class="text" type="text" placeholder="文件md5" /> 62 <p>文件大小(字節)</p> 63 <input id="size" class="text" type="text" placeholder="文件大小(字節)" /> 64 <p></p> 65 <input id="execBtn" class="button" type="button" value="刪除" /> 66 </div> 67 <!-- 結果展示 --> 68 <div class="info"> 69 <p id="text"> 70 </p> 71 </div> 72 </body> 73 <script src="/static/lib/dawn/dawn.js"></script> 74 <script src="/static/lib/chunkupload/chunkupload.js"></script> 75 <script> 76 var execBtn = document.getElementById("execBtn"), 77 md5 = document.getElementById("md5"), 78 size = document.getElementById("size"), 79 text = document.getElementById("text"); 80 81 execBtn.addEventListener("click", function(e) { 82 var block = new Block(md5.value, size.value); 83 84 block.delete(function(info){ 85 text.innerText = JSON.stringify(info); 86 },function(status, text){ 87 text.innerText = "哎呀!出錯啦," + text; 88 }); 89 }); 90 </script> 91 </html> View Code

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved