chunkupload 文件上傳斷點續傳組件(java) - 正式發佈

 chunkupload簡介javascript

     

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

     chunkupload實現以下功能:java

 

     ·  實現斷點續傳web

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

     ·  線程安全chrome

     ·  同一物理機下進程安全api

     ·  文件自動切片,支持合併瀏覽器

     ·  內存佔用小緩存

     ·  高效穩定,高可用安全

     ·  易集成,無第三方依賴

 

     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
相關文章
相關標籤/搜索