使用fileupload組件的原因:
Request對象提供了一個getInputStream()方法,通過這個方法可以讀取到客戶端提交過來的數據,但是由于用戶可能會同時上傳多個文件,在servlet中編程解析這些上傳數據是一件非常麻煩的工作。為方便開發人員處理文件上傳數據,Apache開源組織提供了一個用來處理表單文件上傳的一個開源組件(Commons-fileupload),該組件性能優異,并且使用及其簡單,可以讓開發人員輕松實現web文件上傳功能。
使用Commons-fileupload組件實現文件上傳,需要導入該組件相應的支撐jar包:
commons-fileupload和connons-io
(commons-upload組件從1.1版本開始,它的工作需要commons-io包的支持)
FileUpload組件工作流程:
相應的代碼框架為:
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
package pers.msidolphin.uploadservlet.web; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; 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; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * Servlet implementation class UploadServlet */ public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public UploadServlet() { super (); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取解析工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); //得到解析器 ServletFileUpload parser = new ServletFileUpload(factory); //解決文件名亂碼問題 parser.setHeaderEncoding( "UTF-8" ); //判斷上傳表單類型 if (!ServletFileUpload.isMultipartContent(request)) { return ; } try { //調用解析器解析上傳數據 List<FileItem> fileItems = parser.parseRequest(request); //獲得保存上傳文件目錄的路徑 String uploadPath = request.getServletContext().getRealPath( "/WEB-INF/upload" ); //遍歷List集合 for (FileItem fileItem : fileItems) { //判斷是否為普通表單字段 if (fileItem.isFormField()) { //如果是普通表單字段則打印到控制臺 if (fileItem.getString() == null || "" .equals(fileItem.getString().trim())) { continue ; } System.out.println(fileItem.getFieldName() + " = " + new String(fileItem.getString().getBytes( "ISO-8859-1" ), "UTF-8" )); } else { //獲得文件路徑 String filePath = fileItem.getName(); //如果并未上傳文件,繼續處理下一個字段 if (filePath == null || "" .equals(filePath.trim())) { continue ; } System.out.println( "處理文件:" + filePath); //截取文件名 String fileName = filePath.substring(filePath.lastIndexOf( "\\" ) + 1 ); String reallyName = this .createFileName(fileName); String reallyPath = this .mkDir(reallyName, uploadPath); //下面都是普通的IO操作了 InputStream in = fileItem.getInputStream(); FileOutputStream out = new FileOutputStream(reallyPath + "\\" + reallyName); byte [] buffer = new byte [ 1024 ]; int len = 0 ; while ((len = in.read(buffer)) > 0 ) { out.write(buffer, 0 , len); } out.close(); in.close(); } } System.out.println( "處理完畢..." ); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } //隨機產生唯一的文件名 private String createFileName(String fileName) throws NoSuchAlgorithmException, UnsupportedEncodingException { String extension = fileName.substring(fileName.lastIndexOf( "." )); MessageDigest md = MessageDigest.getInstance( "md5" ); String currentTime = System.currentTimeMillis() + "" ; return UUID.randomUUID() + currentTime + extension; } //根據哈希值產生目錄 private String mkDir(String fileName, String uploadPath) { int hasCode = fileName.hashCode(); //低四位作為一級目錄 int parentDir = hasCode & 0xf ; //二級目錄 int childDir = hasCode & 0xff >> 2 ; File file = new File(uploadPath + "\\" + parentDir + "\\" + childDir); if (!file.exists()) { file.mkdirs(); } uploadPath = uploadPath + "\\" + parentDir + "\\" + childDir; return uploadPath; } } |
JSP頁面 :
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
|
<%@ page language= "java" contentType= "text/html; charset=UTF-8" pageEncoding= "UTF-8" %> <%@ taglib uri= "http://java.sun.com/jsp/jstl/core" prefix= "c" %> <%@ taglib uri= "http://java.sun.com/jsp/jstl/fmt" prefix= "fmt" %> <!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> <fmt:setBundle basename= "pers.msidolphin.uploadservlet.lang.locale" var= "bundle" scope= "page" /> <form action= "<c:url value=" /UploadServlet "/>" method= "post" enctype= "multipart/form-data" > <fmt:message key= "username" bundle= "${bundle}" /><input type= "text" name= "username" /> <br/> <br/> <fmt:message key= "file1" bundle= "${bundle}" /><input type= "file" name= "file1" /> <br/> <br/> <fmt:message key= "file2" bundle= "${bundle}" /><input type= "file" name= "file2" /> <br/> <br/> <input type= "submit" value= "<fmt:message key=" submit " bundle=" ${bundle} "/>" /> </form> </body> </html> |
核心API: DiskFileItemFactory類
1
2
3
4
5
6
|
//設置內存緩沖區的大小,默認為10K,當上傳文件大小大于緩沖區大小,fileupload組件將使用臨時文件緩存上傳文件 public void setSizeThreshold( int sizeThreshold); //指定臨時文件目錄 默認值為System.getProperty("java.io.tmpdir") public void setRepository(java.io.file respository); //構造方法 public DiskFileItemFactory( int sizeThreshold, java.io.file respository); |
核心API: ServletFileUpload類
1
2
3
4
5
6
7
8
9
10
11
12
|
//判斷上傳表單是否為multipart/form-data類型 boolean isMultipartContent(HttpServletRequest request); //解析request對象,并把表單中的每一個輸入項包裝成一個fileitem對象,返回這些對象的list集合 List<FileItem> parseRequest(HttpServletRequest request); //設置上傳文件總量的最大值 單位:字節 void setSizeMax( long sizeMax); //設置單個上傳文件的最大值 單位:字節 void setFileSizeMax( long fileSizeMax); //設置編碼格式,用于解決上傳文件名的亂碼問題 void setHeaderEncoding(String encoding); //設置文件上傳監聽器,作用是實時獲取已上傳文件的大小 void setProgressListener(ProgressListener pListener); |
核心API: FileItem類
1
2
3
4
5
6
7
8
9
10
11
12
|
//判斷表單輸入項是否為普通輸入項(非文件輸入項,如果是普通輸入項返回true boolean isFormField(); //獲取輸入項名稱 String getFieldName(); //獲得輸入項的值 String getString(); String getString(String encoding); //可以設置編碼,用于解決數據亂碼問題 以下是針對非普通字段的: //獲取完整文件名(不同的瀏覽器可能會有所不同,有的可能包含路徑,有的可能只有文件名) String getName(); //獲取文件輸入流 InputStream getInputStream(); |
文件上傳的幾個注意點:
1、上傳文件的文件名亂碼問題:ServletFileUpload對象提供了setHeaderEncoding(String encoding)方法可以解決中文亂碼問題
2、上傳數據的中文亂碼問題:
解決方法一:new String(fileItem.getString().getBytes(“ISO-8859-1”), “UTF-8”)
解決方法二:fileItem.getString(“UTF-8”)
解決方法三:fileItem.getString(request.getCharacterEncoding())
3、上傳文件名的唯一性:UUID、MD5解決方法很多…
4、保存上傳文件的目錄最好不要對外公開
5、限制上傳文件的大小: ServletFileUpload對象提供了setFileSizeMax(long fileSizeMax)和setSizeMax(long sizeMax)方法用于解決這個問題
6、限制文件上傳類型:截取后綴名進行判斷(好像不太嚴格,還要研究一番…)
以上所述是小編給大家介紹的Java中使用fileupload組件實現文件上傳功能的實例代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://blog.csdn.net/mass_effect/article/details/72522857