您好,登錄后才能下訂單哦!
本文結(jié)合具體的范例,介紹如何通過Apache開源類庫提供的軟件包,在Servlet中進(jìn)行文件上傳。本文的參考書籍是《Tomcat與Java Web開發(fā)技術(shù)詳解》第三版,作者:孫衛(wèi)琴。
本文所用的軟件版本為:Window10,JDK10,Tomcat9。
本文所涉及的源代碼的下載網(wǎng)址為:
http://www.javathinker.net/javaweb/upload-app.rar
Apache開源軟件組織提供了與文件上傳有關(guān)的兩個(gè)軟件包:
? fileupload軟件包(commons-fileupload-X.jar):負(fù)責(zé)上傳文件的軟件包,下載網(wǎng)址為:http://commons.apache.org/fileupload/。
該軟件包的使用說明文檔的網(wǎng)址為:http://commons.apache.org/fileupload/using.html。
? I/O軟件包(commons-io-X.jar):負(fù)責(zé)輸入輸出的軟件包,下載網(wǎng)址為:http://commons.apache.org/io/。
應(yīng)該把這兩個(gè)軟件包的JAR文件放在helloapp/WEB-INF/lib目錄下。本書配套源代碼包的sourcecode/chapter05/helloapp/WEB-INF/lib目錄下已經(jīng)提供了以上兩個(gè)JAR文件。Servlet主要利用fileupload軟件包中的接口和類來實(shí)現(xiàn)文件上傳,而fileupload軟件包本身依賴I/O軟件包。以下圖1-1為fileupload軟件包中的主要接口和類的類框圖。
圖1-1 fileupload軟件包中的主要接口和類的類框圖
如下圖1-2所示,對(duì)于一個(gè)正文部分為“multipart/form-data”類型的HTTP請(qǐng)求,uploadfile軟件包把請(qǐng)求正文包含的復(fù)合表單中的每個(gè)子部分看作是一個(gè)FileItem對(duì)象。FileItem對(duì)象分為兩種類型:
? formField:普通表單域類型,表單中的文本域以及提交按鈕等都是這種類型。
? 非formField:上傳文件類型,表單中的文件域就是這種類型,它包含了文件數(shù)據(jù)。
圖1-2 復(fù)合表單中的每個(gè)子部分看作是一個(gè)FileItem對(duì)象
FileItemFactory是創(chuàng)建FileItem對(duì)象的工廠。DiskFileItemFactory類和DiskFileItem類分別實(shí)現(xiàn)了FileItemFactory接口和FileItem接口。DiskFileItem類表示基于硬盤的FileItem,DiskFileItem類能夠把客戶端上傳的文件數(shù)據(jù)保存到硬盤上。DiskFileItemFactory則是創(chuàng)建DiskFileItem對(duì)象的工廠。
以下程序代碼創(chuàng)建了一個(gè)DiskFileItemFactory對(duì)象,然后設(shè)置向硬盤寫數(shù)據(jù)時(shí)所用的緩沖區(qū)的大小,以及所使用的臨時(shí)目錄。在fileupload軟件包自身的實(shí)現(xiàn)中,為了提高向硬盤寫數(shù)據(jù)的效率,尤其是寫大容量數(shù)據(jù)的效率,fileupload軟件包在寫數(shù)據(jù)時(shí)會(huì)使用緩存,以及向臨時(shí)目錄存放一些臨時(shí)數(shù)據(jù)。
//創(chuàng)建一個(gè)基于硬盤的FileItem工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
//設(shè)置向硬盤寫數(shù)據(jù)時(shí)所用的緩沖區(qū)的大小,此處為4K
factory.setSizeThreshold(4*1024);
//設(shè)置臨時(shí)目錄
factory.setRepository(new File(tempFilePath));
ServletFileUpload類為文件上傳處理器,它與FileItemFactory關(guān)聯(lián)。以下程序代碼創(chuàng)建了一個(gè)ServletFileUpload對(duì)象,它與一個(gè)DiskFileItemFactory對(duì)象關(guān)聯(lián)。ServletFileUpload類的setSizeMax()方法用來設(shè)置允許上傳的文件的最大尺寸。
//創(chuàng)建一個(gè)文件上傳處理器
ServletFileUpload upload = new ServletFileUpload(factory);
//設(shè)置允許上傳的文件的最大尺寸,此處為4M
upload.setSizeMax(4*1024*1024);
ServletFileUpload類的parseRequest(HttpServletRequest req)方法能夠解析HttpServletRequest對(duì)象中的復(fù)合表單數(shù)據(jù),返回包含一組FileItem對(duì)象的List集合:
List<FileItem> items = upload.parseRequest(request);
得到了包含F(xiàn)ileItem對(duì)象的List集合后,就可以遍歷這個(gè)集合,判斷每個(gè)FileItem對(duì)象的類型,然后做出相應(yīng)的處理。
for(FileItem item:items){ //遍歷集合中的每個(gè)FileItem對(duì)象
if(item.isFormField()) {
processFormField(item,out); //處理普通的表單域
}else{
processUploadedFile(item,out); //處理上傳文件
}
}
以下例程1-1的UploadServlet類利用fileupload軟件包來處理用戶在upload.htm頁面中上傳的文件。
例程1-1 UploadServlet.java
package mypack;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.fileupload.disk.*;
public class UploadServlet extends HttpServlet {
private String filePath; //存放上傳文件的目錄
private String tempFilePath; //存放臨時(shí)文件的目錄
public void init(ServletConfig config)throws ServletException {
super.init(config);
filePath=config.getInitParameter("filePath");
tempFilePath=config.getInitParameter("tempFilePath");
filePath=getServletContext().getRealPath(filePath);
tempFilePath=getServletContext().getRealPath(tempFilePath);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain");
//向客戶端發(fā)送響應(yīng)正文
PrintWriter out=response.getWriter();
try{
//創(chuàng)建一個(gè)基于硬盤的FileItem工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
//設(shè)置向硬盤寫數(shù)據(jù)時(shí)所用的緩沖區(qū)的大小,此處為4K
factory.setSizeThreshold(4*1024);
//設(shè)置臨時(shí)目錄
factory.setRepository(new File(tempFilePath));
//創(chuàng)建一個(gè)文件上傳處理器
ServletFileUpload upload = new ServletFileUpload(factory);
//設(shè)置允許上傳的文件的最大尺寸,此處為4M
upload.setSizeMax(4*1024*1024);
List<FileItem> items = upload.parseRequest(request);
for(FileItem item:items){
if(item.isFormField()) {
processFormField(item,out); //處理普通的表單域
}else{
processUploadedFile(item,out); //處理上傳文件
}
}
out.close();
}catch(Exception e){
throw new ServletException(e);
}
}
private void processFormField(FileItem item,PrintWriter out){
String name = item.getFieldName();
String value = item.getString();
out.println(name+":"+value+"\r\n");
}
private void processUploadedFile(FileItem item,
PrintWriter out)throws Exception{
String filename=item.getName();
int index=filename.lastIndexOf("\\");
filename=filename.substring(index+1,filename.length());
long fileSize=item.getSize();
if(filename.equals("") && fileSize==0)return;
File uploadedFile = new File(filePath+"/"+filename);
item.write(uploadedFile);
out.println(filename+" is saved.");
out.println("The size of " +filename+" is "+fileSize+"\r\n");
}
web.xml文件中UploadServlet的配置代碼如下:
<servlet>
<servlet-name>upload</servlet-name>
<servlet-class>mypack.UploadServlet</servlet-class>
<init-param>
<param-name>filePath</param-name>
<param-value>store</param-value>
</init-param>
<init-param>
<param-name>tempFilePath</param-name>
<param-value>temp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
UploadServlet有兩個(gè)初始化參數(shù):filePath參數(shù)表示UploadServlet用于存放上傳文件的目錄;tempFilePath參數(shù)表示fileupload軟件包用于存放臨時(shí)文件的目錄。
以下例程1-2的upload.htm定義了一個(gè)用于上傳文件的復(fù)合表單,它有一個(gè)名字為“username”的文本域,還有兩個(gè)用于指定上傳文件的文件域。
例程1-2 upload.htm
<html>
<head>
<title>Upload</title>
</head>
<body >
<form name="uploadForm" method="POST"
enctype="MULTIPART/FORM-DATA"
action="upload">
<table>
<tr>
<td><div align="right">User Name:</div></td>
<td><input type="text" name="username" size="30"/> </td>
</tr>
<tr>
<td><div align="right">Upload File1:</div></td>
<td><input type="file" name="file1" size="30"/> </td>
</tr>
<tr>
<td><div align="right">Upload File2:</div></td>
<td><input type="file" name="file2" size="30"/> </td>
</tr>
<tr>
<td><input type="submit" name="submit" value="upload"></td>
<td><input type="reset" name="reset" value="reset"></td>
</tr>
</table>
</form>
</body>
</html>
從瀏覽器中訪問http://localhost:8080/helloapp/upload.htm,將出現(xiàn)如圖1-3所示的HTML頁面。
圖1-3 upload.htm頁面
對(duì)于圖1-3的upload.htm頁面,在表單中提供圖中所示的數(shù)據(jù),然后提交表單,UploadServlet就會(huì)響應(yīng)本次請(qǐng)求,把“FromClient.rar”以及“FromClient.txt”文件都保存到helloapp/store目錄下,并且向客戶端返回如圖1-4所示的HTML頁面。
圖1-4 UploadServlet返回的HTML頁面
UploadServlet調(diào)用ServletFileUpload對(duì)象的setSizeMax(410241024)方法,把允許上傳的文件的最大尺寸設(shè)為4M。如果在圖1-3的upload.htm頁面中輸入一個(gè)大小超過4M的文件,那么UploadServlet在處理上傳文件時(shí)會(huì)拋出以下異常:
org.apache.commons.fileupload.FileUploadBase
$SizeLimitExceededException:
the request was rejected because its size (7859197)
exceeds the configured maximum (4194304)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。