之前自己寫小項目的時候也碰到過文件上傳的問題,沒有找到很好的解決方案。雖然之前網找各種解決方案的時候也看到過WebUploader,但沒有進一步深究。這次稍微深入了解了些,這里也做個小結。
簡單的文件和普通數據上傳并保存
jsp頁面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<%@ page language= "java" contentType= "text/html; charset=UTF-8" pageEncoding= "UTF-8" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > <title>Insert title here</title> </head> <body> <form action= "${pageContext.request.contextPath }/FileUploadServlet" method= "post" enctype= "multipart/form-data" > 文件:<input type= "file" value= "請選擇文件" name= "file" /> <br/> 信息:<input type= "text" name= "info" /> <br/> <input type= "submit" value= "提交" /> </form> </body> </html> |
servlet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.yihengliu.web.action; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; /** * Servlet user to accept file upload */ public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private String serverPath = "e:/" ; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append( "Served at: " ).append(request.getContextPath()); System.out.println( "進入后臺..." ); // 1.創建DiskFileItemFactory對象,配置緩存用 DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); // 2. 創建 ServletFileUpload對象 ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory); // 3. 設置文件名稱編碼 servletFileUpload.setHeaderEncoding( "utf-8" ); // 4. 開始解析文件 try { List<FileItem> items = servletFileUpload.parseRequest(request); for (FileItem fileItem : items) { if (fileItem.isFormField()) { // >> 普通數據 String info = fileItem.getString( "utf-8" ); System.out.println( "info:" + info); } else { // >> 文件 // 1. 獲取文件名稱 String name = fileItem.getName(); // 2. 獲取文件的實際內容 InputStream is = fileItem.getInputStream(); // 3. 保存文件 FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name)); } } } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
使用WebUploader組件上傳
分片、并發,預覽、壓縮,多途徑添加文件夾(文件多選,拖拽等),妙傳
頁面樣式使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<html> <title>使用webuploader上傳</title> <!-- 1 .引入文件 --> <link rel= "stylesheet" type= "text/css" href= "${pageContext.request.contextPath }/js/webuploader.css" rel= "external nofollow" > <script type= "text/javascript" src= "${pageContext.request.contextPath }/js/jquery-2.1.4.min.js" ></script> <script type= "text/javascript" src= "${pageContext.request.contextPath }/js/webuploader.js" ></script> </head> <body> <!-- 2 .創建頁面元素 --> <div id= "upload" > <div id= "filePicker" >文件上傳</div> </div> <!-- 3 .添加js代碼 --> <script type= "text/javascript" > var uploader = WebUploader.create( { swf: "${pageContext.request.contextPath }/js/Uploader.swf" , server: "${pageContext.request.contextPath }/FileUploadServlet" , pick: "#filePicker" , auto: true } ); </script> </body> </html> |
- 生成文件名列表、實時顯示上傳進度、顯示縮略圖
-
增加文件列表div,
<div id="fileList"></div>
- 生成縮略圖和顯示上傳進度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 生成縮略圖和上傳進度 uploader.on( "fileQueued" , function(file) { // 把文件信息追加到fileList的div中 $( "#fileList" ).append( "<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='percentage'><span></div></div>" ) // 制作縮略圖 // error:不是圖片,則有error // src:代表生成縮略圖的地址 uploader.makeThumb(file, function(error, src) { if (error) { $( "#" + file.id).find( "img" ).replaceWith( "<span>無法預覽 </span>" ); } else { $( "#" + file.id).find( "img" ).attr( "src" , src); } }); } ); // 監控上傳進度 // percentage:代表上傳文件的百分比 uploader.on( "uploadProgress" , function(file, percentage) { $( "#" + file.id).find( "span.percentage" ).text(Math.round(percentage * 100 ) + "%" ); }); |
- 拖拽上傳、粘貼上傳
- 創建拖拽區域并設置樣式:
1
2
3
4
5
6
7
8
9
10
|
<style type= "text/css" > #dndArea { width: 200px; height: 100px; border-color: red; border-style: dashed; } </style> <!-- 創建用于拖拽的區域 --> <div id= "dndArea" ></div> |
- 基本配置中增加dnd區域配置(開啟拖拽)
屏蔽拖拽區域外的響應
開啟粘貼功能
1
2
3
4
5
6
7
8
9
10
11
12
|
var uploader = WebUploader.create( { swf: "${pageContext.request.contextPath }/js/Uploader.swf" , server: "${pageContext.request.contextPath }/FileUploadServlet" , pick: "#filePicker" , auto: true , // 開啟拖拽 dnd: "#dndArea" , // 屏蔽拖拽區域外的響應 disableGlobalDnd: true , // } ); |
- 文件的分塊上傳
前端根據需要發送的文件生成一個md5字符串發送給后臺,后臺創建以該md5字符串命名的文件夾。前端分塊發送文件并發送文件塊序號給后臺,后臺接收到文件后按序號名稱保存。前端發送完成后通知后臺合并文件。
- 前端配置,開啟是否分塊、分塊大小、線程個數等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 上傳基本配置 var uploader = WebUploader.create( { swf: "${pageContext.request.contextPath }/js/Uploader.swf" , server: "${pageContext.request.contextPath }/FileUploadServlet" , pick: "#filePicker" , auto: true , dnd: "#dndArea" , disableGlobalDnd: true , paste: "#uploader" , // 分塊上傳設置 // 是否分塊 chunked: true , // 每塊文件大小(默認5M) chunkSize: 5 * 1024 * 1024 , // 開啟幾個并非線程(默認3個) threads: 3 , // 在上傳當前文件時,準備好下一個文件 prepareNextFile: true } ); |
- 前端監聽分塊
可以分為三個時間點:
- before-send-file: 該方法在文件上傳前調用(只會在一個文件上傳前調用)。
可以在該方法中獲取文件的md5字符串作為后臺保存分塊文件的目錄名
- before-send: 該方法在每個分塊文件上傳前調用(每個分塊上傳前都會調用)。
可以在該方法中發送md5字符串到后臺,后臺判斷是否已經存在分塊決定是否發送以達到斷點續傳的功能
- after-send-file: 該方法在所有文件上傳完成沒有錯誤之后調用(所有分塊上傳完成后調用)。
可以在該方法中通知后臺合并所有分塊
- 前端獲取文件md5字符串,發送每個分塊時發送到后臺,后臺接收如果不存在文件夾創建文件夾,保存分塊發送的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// 監聽分塊上傳的時間點,斷點續傳 var fileMd5; WebUploader.Uploader.register({ "before-send-file" : "beforeSendFile" , "before-send" : "beforeSend" , "after-send-file" : "afterSendFile" },{ beforeSendFile:function(file) { // 創建一個deffered,用于通知是否完成操作 var deferred = WebUploader.Deferred(); // 計算文件的唯一標識,用于斷點續傳和妙傳 ( new WebUploader.Uploader()).md5File(file, 0 , 5 * 1024 * 1024 ) .progress(function(percentage){ $( "#" +file.id).find( "span.state" ).text( "正在獲取文件信息..." ); }) .then(function(val) { fileMd5 = val; $( "#" + file.id).find( "span.state" ).text( "成功獲取文件信息" ); // 放行 deferred.resolve(); }); // 通知完成操作 return deferred.promise(); }, beforeSend:function() { var deferred = WebUploader.Deferred(); // 發送文件md5字符串到后臺 this .owner.options.formData.fileMd5 = fileMd5; deferred.resolve(); return deferred.promise(); }, afterSendFile:function() { } } ); |
添加state標簽
1
|
$( "#fileList" ).append( "<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='state'></span></div><div><span class='percentage'></span></div></div>" ); |
保存文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// 4. 開始解析文件 // 文件md5獲取的字符串 String fileMd5 = null ; // 文件的索引 String chunk = null ; try { List<FileItem> items = servletFileUpload.parseRequest(request); for (FileItem fileItem : items) { if (fileItem.isFormField()) { // >> 普通數據 String fieldName = fileItem.getFieldName(); if ( "info" .equals(fieldName)) { String info = fileItem.getString( "utf-8" ); System.out.println( "info:" + info); } if ( "fileMd5" .equals(fieldName)) { fileMd5 = fileItem.getString( "utf-8" ); System.out.println( "fileMd5:" + fileMd5); } if ( "chunk" .equals(fieldName)) { chunk = fileItem.getString( "utf-8" ); System.out.println( "chunk:" + chunk); } } else { // >> 文件 /*// 1. 獲取文件名稱 String name = fileItem.getName(); // 2. 獲取文件的實際內容 InputStream is = fileItem.getInputStream(); // 3. 保存文件 FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));*/ // 如果文件夾沒有創建文件夾 File file = new File(serverPath + "/" + fileMd5); if (!file.exists()) { file.mkdirs(); } // 保存文件 File chunkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk); FileUtils.copyInputStreamToFile(fileItem.getInputStream(), chunkFile); } } |
- 前端通知action進行合并文件
前端增加:
1
2
3
4
5
6
7
8
9
10
11
12
|
// 通知合并分塊 $.ajax( { type: "POST" , url: "${pageContext.request.contextPath}/UploadActionServlet?action=mergeChunks" , data:{ fileMd5:fileMd5 }, success:function(response){ } } ); |
新增合并action:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
package com.yihengliu.web.action; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 合并上傳文件 */ public class UploadActionServlet extends HttpServlet { private static final long serialVersionUID = 1L; private String serverPath = "e:/" ; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println( "進入合并后臺..." ); String action = request.getParameter( "action" ); if ( "mergeChunks" .equals(action)) { // 獲得需要合并的目錄 String fileMd5 = request.getParameter( "fileMd5" ); // 讀取目錄所有文件 File f = new File(serverPath + "/" + fileMd5); File[] fileArray = f.listFiles( new FileFilter() { // 排除目錄,只要文件 @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { return false ; } return true ; } }); // 轉成集合,便于排序 List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray)); // 從小到大排序 Collections.sort(fileList, new Comparator<File>() { @Override public int compare(File o1, File o2) { if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) { return - 1 ; } return 1 ; } }); // 新建保存文件 File outputFile = new File(serverPath + "/" + UUID.randomUUID().toString() + ".zip" ); // 創建文件 outputFile.createNewFile(); // 輸出流 FileOutputStream fileOutputStream = new FileOutputStream(outputFile); FileChannel outChannel = fileOutputStream.getChannel(); // 合并 FileChannel inChannel; for (File file : fileList) { inChannel = new FileInputStream(file).getChannel(); inChannel.transferTo( 0 , inChannel.size(), outChannel); inChannel.close(); // 刪除分片 file.delete(); } // 關閉流 fileOutputStream.close(); outChannel.close(); // 清除文件加 File tempFile = new File(serverPath + "/" + fileMd5); if (tempFile.isDirectory() && tempFile.exists()) { tempFile.delete(); } System.out.println( "合并文件成功" ); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
- 斷點續傳
前端頁面發送前添加校驗,校驗是否已經上傳分塊
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
beforeSend:function(block) { var deferred = WebUploader.Deferred(); // 支持斷點續傳,發送到后臺判斷是否已經上傳過 $.ajax( { type: "POST" , url: "${pageContext.request.contextPath}/UploadActionServlet?action=checkChunk" , data:{ // 文件唯一表示 fileMd5:fileMd5, // 當前分塊下標 chunk:block.chunk, // 當前分塊大小 chunkSize:block.end-block.start }, dataType: "json" , success:function(response) { if (response.ifExist) { // 分塊存在,跳過該分塊 deferred.reject(); } else { // 分塊不存在或不完整,重新發送 deferred.resolve(); } } } ); // 發送文件md5字符串到后臺 this .owner.options.formData.fileMd5 = fileMd5; return deferred.promise(); } |
- action中添加校驗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
else if ( "checkChunk" .equals(action)) { // 校驗文件是否已經上傳并返回結果給前端 // 文件唯一表示 String fileMd5 = request.getParameter( "fileMd5" ); // 當前分塊下標 String chunk = request.getParameter( "chunk" ); // 當前分塊大小 String chunkSize = request.getParameter( "chunkSize" ); // 找到分塊文件 File checkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk); // 檢查文件是否存在,且大小一致 response.setContentType( "text/html;charset=utf-8" ); if (checkFile.exists() && checkFile.length() == Integer.parseInt((chunkSize))) { response.getWriter().write( "{\"ifExist\":1}" ); } else { response.getWriter().write( "{\"ifExist\":0}" ); } } |
以上所述是小編給大家介紹的Java與WebUploader相結合實現文件上傳功能(實例代碼),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/liuchengcc/p/6643884.html