功能使用webuploader組件分片下載文件 文檔地址: http://fex.baidu.com/webuploader/document.html
從
http://fex.baidu.com/webuploader/download.html中下載
用到的是:
Uploader.swf
webuploader.css
webuploader.min.js
我的目錄
需要jar包:
commons-fileupload-1.3.3.jar
commons-io-2.5.jar
導入jar包方法:Shift+Ctrl+Alt+s
按步驟導入 jar包。。。
webUploader.java
1 package com.example.demo3.upLoader; 2
3 import org.apache.commons.fileupload.FileItem; 4 import org.apache.commons.fileupload.FileUploadException; 5 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 6 import org.apache.commons.fileupload.servlet.ServletFileUpload; 7 import org.apache.commons.io.FileUtils; 8 import org.springframework.stereotype.Controller; 9 import org.springframework.web.bind.annotation.RequestMapping; 10
11 import javax.servlet.ServletException; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 import java.io.File; 15 import java.io.FileInputStream; 16 import java.io.FileOutputStream; 17 import java.io.IOException; 18 import java.util.HashMap; 19 import java.util.List; 20
21 @RequestMapping("uploader.do") 22 @Controller 23 public class WebUpLoaderController { 24 private static final long serialVersionUID = 1L; 25 @RequestMapping("loader") 26 public void douploader(HttpServletRequest request, HttpServletResponse response) 27 throws Exception { 28 String fileName = request.getParameter("fileName"); 29 String fileMd5 = request.getParameter("fileMd5"); 30 String chunk = request.getParameter("chunk"); 31 String chunkSize = request.getParameter("chunkSize"); 32 String guid = request.getParameter("guid"); 33
34 String path = ("C:/upload/uploads"); 35 File checkFile = new File(path+"/"+guid+"/"+chunk); 36
37 response.setContentType("text/html;charset=utf-8"); 38
39 //檢查文件是否存在,且大小是否一致
40 if(checkFile.exists() && checkFile.length()==Integer.parseInt(chunkSize)){ 41 //上傳過
42
43 response.getWriter().write("{\"ifExist\":1}"); 44
45 }else{ 46 //沒有上傳過
47
48 response.getWriter().write("{\"ifExist\":0}"); 49
50 } 51
52 } 53 @RequestMapping("loader2") 54 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 55
56 String path = "C:\\upload\\uploads"; 57 String guid = request.getParameter("guid"); 58 String fileName = request.getParameter("fileName"); 59 /**
60 * 進行文件合並 61 */
62 File file = new File(path+"/"+guid); 63 new File("C:\\upload\\upload"+"/"+guid).mkdirs(); 64 /**
65 * 進行文件合並 66 */
67 File newFile = new File("C:\\upload\\upload"+"/"+guid+"/"+fileName); 68 FileOutputStream outputStream = new FileOutputStream(newFile, true);//文件追加寫入
69 byte[] byt = new byte[10*1024*1024]; 70 int len; 71 FileInputStream temp = null;//分片文件
72 File[] childs = new File(path+"/"+guid).listFiles(); 73 boolean boo = false; 74 if(childs!=null) { 75 for (int i = 0; i < childs.length; i++) { 76 temp = new FileInputStream(childs[i]); 77 while ((len = temp.read(byt)) != -1) { 78 //System.out.println(len);
79 outputStream.write(byt, 0, len); 80 } 81 temp.close(); 82 boo=true; 83 } 84 } 85 /**
86 * 當所有追加寫入都寫完 才可以關閉流 87 */
88 outputStream.close(); 89 if(temp!=null){ 90 temp.close(); 91 } 92 if(boo) { 93 delFolder(path + "/" + guid); 94 } 95
96 } 97 @RequestMapping("loader1") 98 protected void doupload(HttpServletRequest request, HttpServletResponse response) 99 throws ServletException, IOException { 100 String path = "C:\\upload\\uploads"; 101 //DiskFileItemFactory factory = new DiskFileItemFactory(); 102 // 2、創建一個文件上傳解析器
103 ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory()); 104
105 // 設置單個文件的最大上傳值
106 upload.setFileSizeMax(15*1024*1024L); 107 // 設置整個request的最大值
108 upload.setSizeMax(15*1024*1024L); 109 // 解決上傳文件名的中文亂碼
110 upload.setHeaderEncoding("UTF-8"); 111 // fileUpload.setProgressListener(listener); 112 // 3、判斷提交上來的數據是否是上傳表單的數據
113 if (!ServletFileUpload.isMultipartContent(request)) { 114 return; 115 } 116 // 4、使用ServletFileUpload解析器解析上傳數據,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項
117 List<FileItem> list = null; 118 try { 119
120 list = upload.parseRequest(request); 121 // 獲得文件: 122 // MultipartFile file = multipartRequest.getFile(" file ");
123 } catch (FileUploadException e) { 124 e.printStackTrace(); 125 } 126
127 HashMap<String, String> map = new HashMap<String, String>(); 128
129 for (FileItem item : list) { 130 if (item.isFormField()) { 131 String name = item.getFieldName(); 132 // 解決普通輸入項的數據的中文亂碼問題
133 String value = item.getString("UTF-8"); 134
135 map.put(name, value);// 放入map集合
136 } else { 137 /**
138 * 文件上傳 139 */
140
141 File fileParent = new File(path + "/" + map.get("guid"));//以guid創建臨時文件夾
142 if (!fileParent.exists()) { 143 fileParent.mkdir(); 144 } 145
146
147 String filename = item.getName(); 148 if (filename == null || filename.trim().equals("")) { 149 continue; 150 } 151 // 注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: 152 // c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt 153 // 處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分
154 filename = filename.substring(filename.lastIndexOf("\\") + 1); 155
156 //創建文件
157 File file; 158 if (map.get("chunks") != null) { 159 file = new File(fileParent, map.get("chunk")); 160 } else { 161 file = new File(fileParent, "0"); 162 } 163
164 //copy
165 FileUtils.copyInputStreamToFile(item.getInputStream(), file); 166 item.getInputStream().close(); 167 } 168 } 169 } 170 /*** 171 * 刪除文件夾 172 */
173 public static void delFolder(String paths) { 174 try { 175 delAllFile(paths); // 刪除完里面所有內容
176 String filePath = paths; 177 filePath = filePath.toString(); 178 File myFilePath = new File(filePath); 179 myFilePath.delete(); // 刪除空文件夾
180 } catch (Exception e) { 181 e.printStackTrace(); 182 } 183 } 184 /*** 185 * 刪除指定文件夾下所有文件 186 * @return
187 */
188 public static boolean delAllFile(String paths) { 189 boolean flag = false; 190 //判斷這個路徑名是否存在
191 File file = new File(paths); 192 if (!file.exists()) { 193 return flag; 194 } 195 //是否是一個目錄
196 if (!file.isDirectory()) { 197 return flag; 198 } 199 //返回由此抽象路徑名所表示的目錄中的文件和目錄的名稱所組成字符串數組。
200 String[] tempList = file.list(); 201 File temp = null; 202 for (int i = 0; i < tempList.length; i++) { 203 //paths是否以File.separator結束 方便不同平台下使用
204 if (paths.endsWith(File.separator)) { 205 //取一個 刪除一個 ...
206 temp = new File(file + tempList[i]); 207 } else { 208 //取一個 刪除一個 ...
209 temp = new File(file + File.separator + tempList[i]); 210 } 211 //是否是一個標准文件。
212 if (temp.isFile()) { 213 //是的話刪除
214 temp.delete(); 215 flag = true; 216 } 217 //是否是一個目錄,如果是的話先刪除(delAllFile)目錄下的文件,然后再刪除空文件夾
218 if (temp.isDirectory()) { 219 delAllFile(paths + "/" + tempList[i]);// 先刪除文件夾里面的文件
220 delFolder(paths + "/" + tempList[i]);// 再刪除空文件夾
221 flag = true; 222 } 223 } 224 return flag; 225 } 226 }
webUploader.html
1 <!DOCTYPE html>
2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
3 <head>
4 <meta charset="UTF-8">
5 <title>Upload Page</title>
6 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
7 <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
8
9 <script type="text/javascript" src="/upload/jquery-1.7.2.js"></script>
10 <script type="text/javascript" src="/upload/webuploader.min.js"></script>
11 <link href="/upload/webuploader.css" type="css/text" />
12 <script type="text/javascript" src="/upload/jquery-2.0.0.min.js"></script>
13 <script type="text/javascript" src="/upload/jquery-ui.js"></script>
14 <link href="/upload/bootstrap.min.css" rel="stylesheet" media="screen">
15 <script type="text/javascript" src="/upload/bootstrap.min.js"></script>
16
17 </head>
18
19 <body>
20 <div style="margin: 22px 22px 22px 1px;">
21 <div id="picker" class="form-control-focus">選擇文件</div><br/>
22 <p>允許上傳文件類型:<b>.zip .dmp .rar .js .css .xml .7z .ico .pdf .ppt .pptx .xap .xpi .swf .apk .cdf .gif .tar .gz .sh .bmp .jpg</b><br />
23 一次上傳文件大小限制不小於:<b>50</b>MB</p>
24
25 <table id="thelist" class="table table-bordered;uploader-list">
26 <thead>
27 <tr>
28 <th>文件名</th>
29 <th>文件大小</th>
30 <th>狀態</th>
31 <th>操作</th>
32 </tr>
33 </thead>
34 </table>
35
36 </div>
37 <button id="btnSync" type="button" class="btn btn-warning">開始同步</button>
38
39
40
41
42
43 <script>
44 var fileMd5; //文件唯一標識
45
46 /******************下面的參數是自定義的*************************/
47 var fileName;//文件名稱
48 var oldJindu;//如果該文件之前上傳過 已經上傳的進度是多少
49 var count=0;//當前正在上傳的文件在數組中的下標,一次上傳多個文件時使用
50 var filesArr=new Array();//文件數組:每當有文件被添加進隊列的時候 就push到數組中
51 var map={};//key存儲文件id,value存儲該文件上傳過的進度
52 WebUploader.Uploader.register({ 53 "before-send-file":"beforeSendFile",//整個文件上傳前
54 "before-send":"beforeSend", //每個分片上傳前
55 "after-send-file":"afterSendFile", //分片上傳完畢
56 }, 57 { 58 //時間點1:所有分塊進行上傳之前調用此函數
59 beforeSendFile:function(file){ 60 // alert('----');
61 var deferred = WebUploader.Deferred(); 62 //1、計算文件的唯一標記fileMd5,用於斷點續傳 如果.md5File(file)方法里只寫一個file參數則計算MD5值會很慢 所以加了后面的參數:10*1024*1024
63 (new WebUploader.Uploader()).md5File(file,0,10*1024*1024).progress(function(percentage){ 64 $('.'+file.id ).find('p.state').text('正在讀取文件信息...'); 65 }) 66 .then(function(val){ 67 $('.'+file.id ).find("p.state").text("成功獲取文件信息..."); 68 fileMd5=val; 69 uploader.options.formData.guid = fileMd5; 70 console.log("fileMd5:"+fileMd5); 71 //獲取文件信息后進入下一步
72 deferred.resolve(); 73 }); 74
75 fileName=file.name; //為自定義參數文件名賦值
76 return deferred.promise(); 77 }, 78 //時間點2:如果有分塊上傳,則每個分塊上傳之前調用此函數
79 beforeSend:function(block){ 80 // alert('-******-');
81 var deferred = WebUploader.Deferred(); 82 $.ajax({ 83 type:"POST", 84 url:"/uploader.do/loader", //ajax驗證每一個分片
85 data:{ 86 fileName : fileName, 87 fileMd5:fileMd5, //文件唯一標記
88 chunk:block.chunk, //當前分塊下標
89 chunkSize:block.end-block.start,//當前分塊大小
90 guid: uploader.options.formData.guid 91 }, 92 cache: false, 93 async: false, // 與js同步
94 timeout: 1000, 95 dataType:"json", 96 success:function(response){ 97 console.log(block.chunk+"--"+response.ifExist); 98 if(response.ifExist){ 99 //分塊存在,跳過
100 deferred.reject(); 101 }else{ 102 // alert("ss11") 103 //分塊不存在或不完整,重新發送該分塊內容
104 deferred.resolve(); 105 } 106 } 107 }); 108
109 this.owner.options.formData.fileMd5 = fileMd5; 110 deferred.resolve(); 111 return deferred.promise(); 112 }, 113 //時間點3:所有分塊上傳成功后調用此函數
114 afterSendFile:function(){ 115 // alert('-***2222**-'); 116 //如果分塊上傳成功,則通知后台合並分塊
117 $.ajax({ 118 type:"POST", 119 url:"${ctx}/mergeOrCheckChunks.do?param=mergeChunks", //ajax將所有片段合並成整體
120 data:{ 121 fileName : fileName, 122 fileMd5:fileMd5, 123 }, 124 success:function(data){ 125 count++; //每上傳完成一個文件 count+1
126 ; if(count<=filesArr.length-1){ 127 uploader.upload(filesArr[count].id);//上傳文件列表中的下一個文件
128 } 129 //合並成功之后的操作
130 } 131 }) 132 } 133 }); 134 var uploader = WebUploader.create({ 135
136 // swf文件路徑
137 swf : 'upload/Uploader.swf', 138 // 文件接收服務端。
139 server : '/uploader.do/loader1', 140 // 選擇文件的按鈕。可選。 141 // 內部根據當前運行是創建,可能是input元素,也可能是flash.
142 pick : '#picker', 143 chunked: true, //分片處理
144 chunkSize: 10 * 1024 * 1024, //每片5M
145 threads:3,//上傳並發數。允許同時最大上傳進程數。 146 // 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
147 resize : false
148 }); 149
150 function removeSection(e) { 151 // alert("當前第幾行:"+e.parentElement.parentElement.rowIndex) 152 //alert("del:":+e.parentElement.parentElement.removeNode(true)) 153 //var a = e.parentElement.parentElement.rowIndex; 154 //var table=document.getElementById("thelist"); 155 //var objt = $(obj);.remove(); 156 // uploader.removeFile( file );
157 var tr=e.parentNode.parentNode; 158 tr.parentNode.removeChild(tr); 159 //e.parentNode.removeChild(e.parentElement.parentElement.rowIndex); 160 //table.deleteRow(e.parentElement.parentElement.rowIndex); 161 //alert(table) 162 //var len=table.rows.length; 163 //alert(len) 164 // alert("ss"+e.id+"==="+e.name) 165 // $(e).parents(e.id).remove(); 166 // $('[data-spy="scroll"]').each(function () { 167 // var $spy = $(this).scrollspy('refresh') 168 // });
169 } 170 // 當有文件被添加進隊列的時候
171 uploader.on('fileQueued', function(file) { 172 // alert(file.size)
173 var fileName = file.name 174 if (fileName.indexOf('#') >= 0) { 175 alert('文件名中不能有井號'); 176 return false; 177 } 178 if (fileName.indexOf('+') >= 0) { 179 alert('文件名中不能有加號'); 180 return false; 181 } 182 if (fileName.indexOf(' ') >= 0) { 183 alert('文件名中不能有空格'); 184 return false; 185 } 186 var reg = /(\.zip|\.dmp|\.rar|\.js|\.css|\.xml|\.7z|\.ico|\.pdf|\.ppt|\.pptx|\.xap|\.xpi|\.swf|\.apk|\.cdf|\.gif|\.tar|\.gz|\.sh|\.bmp|\.jpg)$/ig; 187 if (!reg.test(fileName)) { 188 var supportType = reg.toString().replace(/\/|\(|\)|\\|/ig, ''); 189 supportType = supportType.substring(0, supportType.length - 3); 190 supportType = supportType.replace(/\|/g, ' '); 191 alert('不支持該上傳文件類型!\n支持的文件類型:' + supportType); 192 // return false;
193 } 194 if (file.size < 50*1024*1024) 195 { 196 alert('上傳文件大小不能小於' + 50 + 'MB'); 197 // return false;
198 } 199 // alert(123);
200 $("#thelist").append( 201 '<tr class="'+ file.id +'">'
202 +'<td ><h4 class="info">' + file.name + '</h4></td>'
203 +'<td><font face="宋體" size=3 color="red">'+ file.size +' </font>'+'字節'+'</td>'
204 +'<td id="' + file.id + '"><p class="state">等待上傳...</p></td>'//onclick="removeSection(this);"
205 +'<td><input type="button" class="remove-this" name="sss" id="'+ file.id +'" value="刪除" class="btn btn-default"/></td>'
206 +'</tr>'); 207 }); 208
209 uploader.on('uploadProgress', function(file,percentage) { 210
211 var $li = $('#' + file.id), 212 $percent = $li.find('.progress .progress-bar'); 213
214 // 避免重復創建
215 if (!$percent.length) { 216 $percent = $('<div id="' + file.id + '" class="progress progress-striped active">' +
217 '<div class="progress-bar" style="height:20px; role="progressbar" style="width: 0%">' +
218 '</div>' +
219 '</div>').appendTo($li).find('.progress-bar'); 220 } 221
222 $('.'+file.id ).find('p.state').text('上傳中'); 223 $percent.css('width', percentage * 100 + '%'); 224 }); 225
226 uploader.on('uploadSuccess', function(file) { 227 $('.' + file.id).find('p.state').text('已上傳'); 228 $.post("/uploader.do/loader2", { "guid": uploader.options.formData.guid,fileName:file.name}, 229 function(data){ 230 }, "json"); 231 }); 232
233 uploader.on('uploadError', function(file) { 234 $('.' + file.id).find('p.state').text('上傳出錯'); 235 }); 236
237 uploader.on('uploadComplete', function(file) { 238 $('.' + file.id).find('.progress').fadeOut(); 239 }); 240
241 uploader.on( 'beforeFileQueued', function( file ) { 242
243 // alert(file.size);
244
245 }); 246
247 $("#btnSync").on('click', function() { 248 if ($(this).hasClass('disabled')) { 249 return false; 250 } 251 console.log("get fileMd5:"+fileMd5); 252
253 uploader.upload(); 254
255 }); 256 </script>
257 </body>
258 </html>
application.propertise
#文件分片上傳關閉multipart,不然的話request被預編譯,文件解析器解析請求為空 spring.servlet.multipart.enabled=false
遇到的問題:
list = upload.parseRequest(request);(74行) list為空
我用Meclipse可以,idea就不行了,很納悶。
網上找了很多,知道request被預編譯,但是說法大多數struts配置影響的還有一些其他方法,
看來下,卧槽,那么復雜,我這么lazy,算了,再找找其他的。
最后在一片博文找到了方法,在application.propertise中
關閉multipart,問題解決
spring.servlet.multipart.enabled=false