本文為大家分享了java組件實現文件上傳功能的具體代碼,供大家參考,具體內容如下
1 SmartUpload上傳組件
SmartUpload上傳組件包,可以輕松的實現文件的上傳和下載功能;
使用簡單,實現上傳文件類型的限制,也可以輕易的取得上傳文件的名稱、后綴、大小等;
SmartUpload本身是系統提供的jar包,將此包考入到lib文件夾中;
此組件的提供方網站已關閉,SmartUpload在非框架中開發中較為好用;
上傳單個文件
要進行上傳,必須使用HTML中提供給的file空間,而且<form>必須使用enctype屬性進行封裝;
smartupload_demo01.html : 上傳表單
1
2
3
4
5
6
7
8
9
|
< html > < head >< title >上傳表單</ title ></ head > < body > < form action = "smartupload_demo01.jsp" method = "post" enctype = "multipart/form-data" > 請選擇要上傳的文件:< input type = "file" name = "pic" > < input type = "submit" value = "上傳" > </ form > </ body > </ html > |
在form上使用enctype進行了表單封裝,表示表單將按二進制的方式提交,即所有的表單此時不在是分別提交,而是將所有的內容都按照二進制的方式提交;
smartupload_demo01.jsp : 接收圖片,保存在根目錄中的upload文件夾中
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<%@ page contentType="text/html" pageEncoding="GBK"%> <%@ page import="org.bug.smart.*"%> < html > < head >< title >接收圖片,保存在根目錄中的upload文件夾中</ title ></ head > < body > <% SmartUpload smart = new SmartUpload() ; smart.initialize(pageContext) ; // 初始化上傳操作 smart.upload() ; // 上傳準備 smart.save("upload") ; // 文件保存 %> </ body > </ html > |
使用SmartUpload時必須嚴格按照如上程序進行,最后在保存時只是寫了一個upload,表示上傳文件的保存文件夾,此文件要在根目錄中手工建立;
保存的名稱和上傳的文件一樣,所以如果出現相同的文件名稱,將出現覆蓋的情況;
混合表單
當一個表單使用了enctyoe封裝后,其它文件類的表單控件的內容將無法通過request內置對象取得;
此時,必須通過SmartUpload類中提供的getRequest()方法取得全部的請求參數;
smartupload_demo02.html ; 混合表單
1
2
3
4
5
6
7
8
9
10
11
|
< html > < head >< title >混合表單</ title ></ head > < body > < form action = "smartupload_demo02.jsp" method = "post" enctype = "multipart/form-data" > 姓名:< input type = "text" name = "uname" >< br > 照片:< input type = "file" name = "pic" >< br > < input type = "submit" value = "上傳" > < input type = "reset" value = "重置" > </ form > </ body > </ html > |
以上表單中包含了文本和文件兩個控件;
smartupload_demo02.jsp : 接收封裝表單的文本數據
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<%@ page contentType="text/html" pageEncoding="GBK"%> <%@ page import="org.bug.smart.*"%> <%@ page import="cn.com.bug.util.*"%> < html > < head >< title >接收封裝表單的文本數據</ title ></ head > < body > <% request.setCharacterEncoding("GBK") ; %> <% SmartUpload smart = new SmartUpload() ; smart.initialize(pageContext) ; // 初始化上傳操作 smart.upload() ; // 上傳準備 String name = smart.getRequest().getParameter("uname") ; smart.upload("upload");%> < h2 >姓名:<%=name%></ h2 > < h2 >request無法取得 : <%=request.getParameter("uname")%> </ h2 > </ body > </ html > |
表單進行了二進制封裝,單靠request對象是無法取得提交參數的,必須依靠SmartUpload類中的getRequest().getParameter()方法才能取得請求的參數;
由于是通過SmartUpload完成參數接收,所以smart.getRequest()方法一定要在執行完upload()方法后才可使用;
為上傳文件自動命名
為了解決文件名稱相同而出現覆蓋的情況,可以采用為上傳文件自動命名的方式;
自動命名可采用格式: IP地址+時間戳+三位隨機數
IPTimeStamp.java : 定義取得IP時間戳的操作類
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
|
package cn.com.bug.util ; import java.text.SimpleDateFormat ; import java.util.Date ; import java.util.Random ; public class IPTimeStamp { private SimpleDateFormat sdf = null ; //定義SimpleDateFormat對象 private String ip = null ; //接收IP地址 public IPTimeStamp(){ } public IPTimeStamp(String ip){ //得到IP地址+時間戳+三位隨機數 this .ip = ip ; } public String getIPTimeRand(){ StringBuffer buf = new StringBuffer() ; //實例化StringBuffer對象 if ( this .ip != null ){ String s[] = this .ip.split( "\\." ) ; //進行拆分操作 for ( int i= 0 ;i<s.length;i++){ //循環設置IP地址 buf.append( this .addZero(s[i], 3 )) ; //不夠三位要補0 } } buf.append( this .getTimeStamp()) ; //取得時間戳 Random r = new Random() ; //定義Random對象,已產生隨機數 for ( int i= 0 ;i< 3 ;i++){ //循環三次 buf.append(r.nextInt( 10 )) ; //增加隨機數 } return buf.toString() //返回名稱 } public String getDate(){ //取得當前系統的時間 this .sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" ) ; return this .sdf.format( new Date()) ; } public String getTimeStamp(){ //取得時間戳 this .sdf = new SimpleDateFormat( "yyyyMMddHHmmssSSS" ) ; return this .sdf.format( new Date()) ; } private String addZero(String str, int len){ //補0操作 StringBuffer s = new StringBuffer() ; s.append(str) ; while (s.length() < len){ s.insert( 0 , "0" ) ; } return s.toString() ; } public static void main(String args[]){ System.out.println( new IPTimeStamp( "192.168.1.1" ).getIPTimeRand()) ; } } |
直接修改上傳的操作頁,在上傳的操作頁中不直接使用save()方法保存;
而是取得一個具體上傳文件對象才可以保存,由于上傳文件時文件的后綴需要統一,所以可以使用getFileExt()方法取得文件的后綴;
smartupload_demo02.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
|
<%@ page contentType="text/html" pageEncoding="GBK"%> <%@ page import="org.bug.smart.*"%> <%@ page import="cn.com.bug.util.*"%> < html > < head >< title >修改后的smartuoload.jsp</ title ></ head > < body > <% request.setCharacterEncoding("GBK") ; %> <% SmartUpload smart = new SmartUpload() ; smart.initialize(pageContext) ; // 初始化上傳操作 smart.upload() ; // 上傳準備 String name = smart.getRequest().getParameter("uname") ; IPTimeStamp its = new IPTimeStamp(request.getRemoteAddr()) ; // 取得客戶端的IP地址 String ext = smart.getFiles().getFile(0).getFileExt() ; // 擴展名稱 String fileName = its.getIPTimeRand() + "." + ext ; smart.getFiles().getFile(0).saveAs(this.getServletContext().getRealPath("/")+"upload"+java.io.File.separator + fileName) ; %> <%=smart.getFiles().getFile(0).getFileName().matches("^\\w+.(jpg|gif)$")%> < h2 >姓名:<%=name%></ h2 > < img src="../upload/<%=fileName%>"> </ body > </ html > |
由于SmartUpload可以同時接收多個文件;
此時通過smart.getFiles().getFile(0).getFileExt()取得第一個上傳文件的文件后綴,在與之前IPTimeStampl類生成的文件名稱一起拼湊出一個新的文件名;
此時要用的新的文件名稱保存上傳文件,所以要通過smart.getFiles().getFile(0).saveAs()方法進行收工保存;
以上代碼沒有對上傳文件的類型進行限制,可以通過正則判斷文件的后綴是否合法;
eg:驗證上傳文件的合法性代碼片段
1
2
3
|
if (smart.getFiles().getFile( 0 ).getFileName().matches( "^\\w+\\.(jsp|gif)$" )){ //表示只允許后綴為jpg或gif的文件上傳; } |
批量上傳
smart.getFiles().getFile(0).saveAs(this.getServletContext().getRealPath("/")+"upload"+java.io.File.separator + fileName) ;
以上證明可以一次性提交多個上傳文件;
smartupload_demo03.jsp : 編寫表單,上傳3個文件
1
2
3
4
5
6
7
8
9
10
11
12
|
< html > < head >< title >編寫表單,上傳3個文件</ title ></ head > < body > < form action = "smartupload_demo03.jsp" method = "post" enctype = "multipart/form-data" > 照片1:< input type = "file" name = "pic1" >< br > 照片2:< input type = "file" name = "pic2" >< br > 照片3:< input type = "file" name = "pic3" >< br > < input type = "submit" value = "上傳" > < input type = "reset" value = "重置" > </ form > </ body > </ html > |
如果要完成批量上傳,則肯定要使用循環的方式進行,必須通過以下方式取得上傳文件數量;
取得上傳文件的數量:smart.getFiles().getCount();
smartupload_demo03.jsp : 批量上傳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<%@ page contentType="text/html" pageEncoding="GBK"%> <%@ page import="org.bug.smart.*"%> <%@ page import="cn.com.bug.util.*"%> < html > < head >< title >批量上傳</ title ></ head > < body > <% request.setCharacterEncoding("GBK") ; %> <% SmartUpload smart = new SmartUpload() ; smart.initialize(pageContext) ; // 初始化上傳操作 smart.upload() ; // 上傳準備 String name = smart.getRequest().getParameter("uname") ; IPTimeStamp its = new IPTimeStamp(request.getRemoteAddr()) ; // 取得客戶端的IP地址 for(int x=0;x< smart.getFiles ().getCount();x++){ String ext = smart .getFiles().getFile(x).getFileExt() ; // 擴展名稱 String fileName = its .getIPTimeRand() + "." + ext ; smart.getFiles().getFile(x).saveAs(this.getServletContext().getRealPath("/")+"upload"+java.io.File.separator + fileName) ; } %> </ body > </ html > |
FileUpload是Apache組織提供的免費上傳組件,可以直接從站點進行下載(http://commons.apache.org/fileupload/);
FileUpload組件本身依賴于Commons組件包,所以從Apache下載此組件的同時連同Commons組件的IO包一起下載(http://commons.apache.org/io);
Commons組件包在很多框架開發中都可以直接使用,此包中提供了大量開發類可作為java的有力補充;
將Commons-fileupload-1.2.1.jar和Common-io-1.4.jar配置到lib文件夾中;
使用FileUpload接收上傳內容
不論是使用SmartUpload和FileUpload進行上傳操作,都是依靠HTML的file控件完成的;
fileupload_demo01.html : 上傳表單
1
2
3
4
5
6
7
8
9
10
11
|
< html > < head >< title >上傳表單</ title ></ head > < body > < form action = "fileupload_demo01.jsp" method = "post" enctype = "multipart/form-data" > 姓名:< input type = "text" name = "uname" >< br > 照片:< input type = "file" name = "pic" >< br > < input type = "submit" value = "上傳" > < input type = "reset" value = "重置" > </ form > </ body > </ html > |
FileUpload的具體上傳操作與SmartUpload相比有著很高的復雜度;
以下是FileUpload上傳的步驟:
1 創建磁盤工廠:DiskFileItemFactory factory = new DiskFileFactory();
2 創建處理工具:ServletFileUpload upload =new ServletFileUpload(factory);
3 設置文件的上傳大小:upload.setFileSizeMax(3145728);
4 接收全部的內容:List<FileItem> items = upload.parseRequest(request);
FileUpload對所有的上傳內容都采用同樣的方式操作;
與SmartUpload不同的是,會將所有的上傳內容一起(包括文件和普通參數)接收;
所以需要依次判斷你每一次上傳的內容是文件還是普通文本;
fileupload_demo01.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<%@ page contentType="text/html" pageEncoding="GBK"%> <%@ page import="java.util.*"%> <%@ page import="org.apache.commons.fileupload.*"%> <%@ page import="org.apache.commons.fileupload.disk.*"%> <%@ page import="org.apache.commons.fileupload.servlet.*"%> < html > < head >< title >接收上傳文件</ title ></ head > < body > <% DiskFileItemFactory factory = new DiskFileItemFactory() ; ServletFileUpload upload = new ServletFileUpload(factory) ; upload.setFileSizeMax(3 * 1024 * 1024) ; // 只能上傳3M List< FileItem > items = upload.parseRequest(request) ; // 接收全部內容 Iterator< FileItem > iter = items.iterator() ;//將全部的內容變為Iterator實例 while(iter.hasNext()){ //依次取出每一個內容 FileItem item = iter.next() ; //取出每一個上傳的文件 String fieldName = item.getFieldName() ; // 取得表單控件的名稱 %> < ul >< h4 ><%=fieldName%> --> <%=item.isFormField()%></ h4 > <% if(!item.isFormField()){ // 不是普通文本 String fileName = item.getName() ; // 取得文件的名稱 String contentType = item.getContentType() ; // 文件類型 long sizeInBytes = item.getSize() ;//文件大小 %> < li >上傳文件名稱:<%=fileName%> < li >上傳文件類型:<%=contentType%> < li >上傳文件大小:<%=sizeInBytes%> <% } else { String value = item.getString() ; %> < li >普通參數:<%=value%> <% } %> </ ul > <% } %> </ body > </ html > |
FileUpload組件接收完全部的數據后,所有的數據都保存在List集合中,則需要使用Iterator取出每一個數據;
但是由于其中既有普通的文本數據又有上傳的文件,每一個上傳內容都使用一個FileItem類對象表示;
所以當使用Iterator依次取出每一個FileItem對象時,就可以使用FileItem類中的isFormField()方法來判斷當前操作的內容是普通的文本還是附件上傳;
如果是上傳文件,則將文件的內容依次取出;如果是普通的文本,則直接通過getString()方法取得具體的信息;
保存上傳內容
以上完成了接收上傳文件內容的操作,但是所上傳的文件現在并沒有真正的保存在服務器上;
而要進行文件的保存,在FileUpload中就必須通過java.io包中InputStream和outputStream兩個類完成文件的自動命名操作;
InputStream和OutputStream為兩個抽象類,必須依靠FileInputStream和OutputStream類進行對象的實例化操作;
fileupload_demo02.html : 定義上傳表單,可以同時上傳多個文件
1
2
3
4
5
6
7
8
9
10
11
12
13
|
< html > < head >< title >定義表單,可以同時上傳多個文件</ title ></ head > < body > < form action = "fileupload_demo02.jsp" method = "post" enctype = "multipart/form-data" > 姓名:< input type = "text" name = "uname" >< br > 照片:< input type = "file" name = "pic1" >< br > 照片:< input type = "file" name = "pic2" >< br > 照片:< input type = "file" name = "pic3" >< br > < input type = "submit" value = "上傳" > < input type = "reset" value = "重置" > </ form > </ body > </ html > |
fileupload_demo02.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<%@ page contentType="text/html" pageEncoding="GBK"%> <%@ page import="java.util.*,java.io.*"%> <%@ page import="org.apache.commons.fileupload.*"%> <%@ page import="org.apache.commons.fileupload.disk.*"%> <%@ page import="org.apache.commons.fileupload.servlet.*"%> <%@ page import="cn.com.bug.util.*"%> < html > < head >< title >保存上傳內容</ title ></ head > < body > <% DiskFileItemFactory factory = new DiskFileItemFactory() ; factory.setRepository(new File(this.getServletContext().getRealPath("/") + "uploadtemp")) ; // 設置一個臨時文件 ServletFileUpload upload = new ServletFileUpload(factory) ; upload.setFileSizeMax(3 * 1024 * 1024) ; // 只能上傳3M List< FileItem > items = upload.parseRequest(request) ; // 接收全部內容 Iterator< FileItem > iter = items.iterator() ; //將全部的內容轉換為Iterator實例 IPTimeStamp its = new IPTimeStamp(request.getRemoteAddr()) ;//實例化IP時間戳對象 while(iter.hasNext()){//依次取出每一個內容 FileItem item = iter.next() ; //取出每一個上傳的文件 String fieldName = item.getFieldName() ; // 取得表單控件的名稱 %> < ul >< h4 ><%=fieldName%> --> <%=item.isFormField()%></ h4 > <% if(!item.isFormField()){ // 不是普通文本,是上傳文件 File saveFile = null ; //定義保存的文件 InputStream input = null ; OutputStream output = null ; input = item.getInputStream() ; output = new FileOutputStream(new File(this.getServletContext().getRealPath("/")+"upload"+File.separator+its.getIPTimeRand()+ "."+item.getName().split("\\.")[1])) ;//定義輸入文件的路徑 int temp = 0 ; byte data[] = new byte[512] ; while((temp=input.read(data,0,512))!=-1){ //依次讀取內容 output.write(data) ; // 分塊保存 } input.close() ; output.close() ; } else { String value = item.getString() ;//取出表單的內容 %> < li >普通參數:<%=value%> <% } %> </ ul > <% } %> </ body > </ html > |
以上代碼中,首先會將所有的上傳文件設置到臨時文件夾中;
如果發現取得的表單是上傳文件,則使用InputStream,從FileItem類中取得文件的輸入流;
在使用OutputStream將內容依次取出,保存在具體的文件路徑中;
FileUpload在建的不便之處:
1 無法像使用request.getParameter()方法那樣準確地取得提交的參數;
2 無法像使用request.getParameterValues()那樣準確的取得一組提交參數;
3 所有的上傳文件度需要進行一次的判斷,才能夠分別保存,不能一次性批量保存;
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/shici/archive/2017/11/14/7751500.html