這是一個Servlet應用。。
首先是web.xml
<?xml version="1.0" encoding="UTF-8"?><br /><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"<br />xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />xsi:schemaLocation="http://java.sun.com/xml/ns/javaee<br />http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><br /><servlet><br /><servlet-name>UploadServlet</servlet-name><br /><servlet-class>com.jadyer.servlet.FileUploadServlet</servlet-class><br /></servlet><br /><servlet-mapping><br /><servlet-name>UploadServlet</servlet-name><br /><url-pattern>/UploadServlet</url-pattern><br /></servlet-mapping><br /><welcome-file-list><br /><welcome-file>upload.jsp</welcome-file><br /></welcome-file-list><br /></web-app>
然後是用來選擇所要上傳的檔案的upload.jsp頁面
<%@ page language="java" pageEncoding="UTF-8"%><br /><%--<br />===================================================================================<br />【上傳檔案時表單的method和enctype屬性】<br />普通<form>表單的method屬性預設為GET,enctype屬性預設為application/x-www-form-urlencoded<br />但在上傳檔案時,表單method值必須是POST,enctype需要設定為multipart/form-data<br />並且enctype屬性是通過表單上傳檔案必不可少的參數,上傳檔案時需將其顯式設定為multipart/form-data<br />預設的application/x-www-form-urlencoded只是用來指明表單資料在提交時,是以字串資訊進行提交的<br />若未指定multipart/form-data值,將導致request.getParameter("file")只能獲得包含路徑的檔案名稱<br />===================================================================================<br />--%><br /><form action="<%=request.getContextPath()%>/UploadServlet" method="POST" enctype="multipart/form-data"><br /><table border="9"><br /><tr><br /><td>username</td><br /><td><input type="text" name="username"></td><br /></tr><br /><tr><br /><td>password</td><br /><td><input type="password" name="password"></td><br /></tr><br /><tr><br /><td>File11</td><br /><td><input type="file" name="file11"></td><br /></tr><br /><tr><br /><td>File22</td><br /><td><input type="file" name="file22"></td><br /></tr><br /><tr><br /><td> </td><br /><td><input type="submit" name="submit" value="上傳"></td><br /></tr><br /></table><br /></form>
接著是用來顯示檔案上傳結果的result.jsp頁面
<%@ page language="java" pageEncoding="UTF-8"%></p><p><h3>請移步D:/Program Files/tomcat6/webapps/upload/uploadFile/查看所上傳的檔案</h3><br /><table border="9"><br /><tr><br /><td>uploadResult</td><br /><td>${requestScope['upload.message']}</td><br /></tr><br /><tr><br /><td>username</td><br /><td>${requestScope.username}</td><br /></tr><br /><tr><br /><td>password</td><br /><td>${requestScope.password}</td><br /></tr><br /><tr><br /><td>File11</td><br /><td>${requestScope.file11}</td><br /></tr><br /><tr><br /><td>File22</td><br /><td>${requestScope.file22}</td><br /></tr><br /></table>
最後是用來處理檔案上傳的核心Servlet
package com.jadyer.servlet;</p><p>import java.io.File;<br />import java.io.IOException;<br />import java.util.List;</p><p>import javax.servlet.ServletException;<br />import javax.servlet.http.HttpServlet;<br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;</p><p>import org.apache.commons.fileupload.FileItem;<br />import org.apache.commons.fileupload.disk.DiskFileItemFactory;<br />import org.apache.commons.fileupload.servlet.ServletFileUpload;</p><p>/**<br /> * 實現檔案上傳操作的Servlet<br /> * @author 玄玉<br /> */<br />public class FileUploadServlet extends HttpServlet {<br />private static final long serialVersionUID = 7291295547319094602L;</p><p>public void doPost(HttpServletRequest request, HttpServletResponse response)<br />throws ServletException, IOException {<br />request.setCharacterEncoding("UTF-8");</p><p>//雖然getRealPath()方法已經不贊同被使用了,但是它還是很好用的<br />//getRealPath("/uploadFile")指的就是WebRoot下的uploadFile目錄<br />String path = request.getRealPath("/uploadFile");</p><p>// 建立工廠。然後再通過工廠來設定兩個相關的屬性<br />// Create a factory for disk-based file items<br />// DiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);<br />DiskFileItemFactory factory = new DiskFileItemFactory();</p><p>// 設定小於1MB的檔案就放到記憶體中,大於等於1MB則寫到磁碟中<br />// Set yourMaxMemorySize<br />factory.setSizeThreshold(1024 * 1024);<br />// 設定臨時儲存目錄<br />// Set yourTempDirectory<br />factory.setRepository(new File(path));</p><p>// 通過工廠產生類的執行個體<br />// Create a new file upload handler<br />ServletFileUpload upload = new ServletFileUpload(factory);</p><p>// 設定允許使用者上傳檔案大小, 單位:位元組<br />// Set overall request size constraint<br />// factory.setSizeMax(yourMaxRequestSize);</p><p>try {<br />// parse是解析的意思,parseRequest也就是解析傳過來的內容<br />// 調用ServletFileUpload類的parseRequest()方法擷取所上傳的所有檔案和參數的集合<br />// Parse the request<br />List<FileItem> list = upload.parseRequest(request);</p><p>//遍曆list對象中的每個FileItem對象,FileItem對象代表表單參數和所上傳的檔案<br />//然後判斷它到底是不是File類型的<br />for (FileItem item : list) {<br />// Process a regular form field<br />if (item.isFormField()) {<br />String name = item.getFieldName();//獲得欄位的名字<br />String value = item.getString("UTF-8");//使用指定編碼獲得欄位的值<br />request.setAttribute(name, value);//用於在result.jsp頁面中輸出<br />} else {<br />// Process a file upload<br />// If you want to process a file upload in memory, you can use code as: byte[] data = item.get();<br />if (null!=item.getName() && !"".equals(item.getName())) {<br />//通過FileItem對象的getName()方法所擷取的是上傳檔案在用戶端的包含尾碼的完整名稱<br />//並且FileItem對象的getSize()、getContentType()可以擷取所上傳的檔案的大小和類型<br />System.out.println("上傳檔案的名稱:" + item.getName());<br />System.out.println("上傳檔案的大小:" + item.getSize());<br />System.out.println("上傳檔案的類型:" + item.getContentType());</p><p>System.out.println("-------------------------------------------------");</p><p>String value = item.getName();<br />int start = value.lastIndexOf("//");<br />String fileName = value.substring(start + 1);</p><p>//使用FileItem對象writer()方法完成最終的上傳檔案的儲存<br />item.write(new File(path, fileName));</p><p>//用於在result.jsp中顯示所上傳的檔案名稱<br />String name = item.getFieldName();<br />request.setAttribute(name, fileName);</p><p>request.setAttribute("upload.message", "檔案上傳成功");<br />}else{<br />request.setAttribute("upload.message", "沒有選擇上傳檔案");<br />}<br />}<br />}<br />}<br />catch (Exception ex) {<br />ex.printStackTrace();<br />request.setAttribute("upload.message", "檔案上傳失敗");<br />}<br />request.getRequestDispatcher("result.jsp").forward(request,response);<br />}<br />}<br />/***************【淺析DiskFileItemFactory類】**************************************************************/<br />//查看org.apache.commons.fileupload.disk.DiskFileItemFactory的API文檔<br />//觀察DiskFileItemFactory的名字,翻譯過來就是磁碟檔案條目的工廠,因此它肯定是跟磁碟的檔案有關係的<br />//DiskFileItemFactory中有兩個setter()方法,分別為setSizeThreshold()和setRepository()方法<br />/***************【淺析setSizeThreshold()方法】**************************************************************/<br />//在API文檔中setSizeThreshold()的原形是public void setSizeThreshold(int sizeThreshold)<br />//描述:Sets the size threshold beyond which files are written directly to disk<br />//翻譯:設定上傳檔案的最大體積。如果超出這個size的話,檔案就被直接寫到磁碟裡面<br />//也就是說指定上傳檔案的體積。如果上傳的檔案小於這個體積,就直接把檔案放到記憶體裡面。如果超出這個體積的話,就把檔案放到磁碟裡面<br />/***************【淺析setRepository()方法】*****************************************************************/<br />//在API文檔中setRepository()的原形是public void setRepository(java.io.File repository)<br />//描述:Sets the directory used to temporarily store files that are larger than the configured size threshold<br />//翻譯:設定用來臨時的隱藏檔的目錄,而且儲存的檔案是比配置的threshold要大的檔案<br />//也就是說setRepository()是用來設定臨時目錄的。一旦上傳的檔案超出了所設定的大小時,就把這個檔案臨時的儲存到這個目錄裡面<br />/***************【淺析ServletFileUpload類】****************************************************************/<br />//最重要的就是org.apache.commons.fileupload.servlet.ServletFileUpload類,它是真正用來處理上傳操作的<br />//在以前的版本中,使用的是org.apache.commons.fileupload.DiskFileUpload類進行上傳的<br />//DiskFileUpload描述為:Deprecated.Use ServletFileUpload together with DiskFileItemFactory instead<br />//翻譯過來就是:使用ServletFileUpload和DiskFileItemFactory來代替DiskFileUpload<br />//以前是不用工廠的,直接New出來DiskFileUpload的執行個體就可以了。但是現在就不要再使用DiskFileUpload類了<br />//ServletFileUpload類有一個這樣的構造方法ServletFileUpload(FileItemFactory fileItemFactory)。它的描述如下<br />//Constructs an instance of this class which uses the supplied factory to create FileItem instances<br />//這個構造方法使用的是FileItemFactory類型的參數。查看源碼可知DiskFileItemFactory類實現了FileItemFactory<br />//因此,在構建ServletFileUpload執行個體的時候,就可以使用DiskFileItemFactory作為構造方法的參數來產生執行個體<br />//這樣就通過工廠產生了ServletFileUpload類的一個執行個體了<br />/***************【淺析parseRequest()方法】******************************************************************/<br />//在ServletFileUpload類中提供了一個parseRequest()方法,它的原始碼如下所示<br />//--------------------------------------------------------------------------------------------------<br />//public List /* FileItem */ parseRequest(HttpServletRequest request) throws FileUploadException{ |<br />//return parseRequest(new ServletRequestContext(request)); |<br />//} |<br />//--------------------------------------------------------------------------------------------------<br />//parseRequest()方法是真正完成上傳的處理的,它是非常複雜的一個方法。它接收的是一個HttpServletRequest參數<br />//我們知道,用戶端傳過來的東西,都是在request中的。這裡的parseRequest()就會解析request,得到java.util.list<br />//這個List就封裝了用戶端傳過來的表單裡面的所有的參數,也包括File類型。它會將這些參數封裝成一個集合,便於我們使用<br />//其中/* FileItem */用來說明所返回的List中都是FileItem類型的。為了相容JDK1.4,所以它沒有用泛型的方式來定義<br />//注意,一個FileItem對應的是表單中的一個欄位,而並不僅僅是表單中的File類型的欄位,也不是表單中所有欄位的集合<br />/***************【淺析FileItem介面和它的isFormField()方法】***************************************************/<br />//通過查看org.apache.commons.fileupload.FileItem的API發現FileItem是一個介面<br />//但是我們不必關心它是由什麼類來具體實現的,這就是面向介面編程的一個好處<br />//在FileItem介面中有一個boolean isFormField()方法,它的描述如下<br />//Determines whether or not a FileItem instance represents a simple form field<br />//翻譯過來就是:決定FileItem執行個體是否代表一個簡單的表單欄位<br />//表單欄位只有兩種,即File類型和非File類型。如果isFormField()返回TRUE則表明是非File的,返回FALSE則表明是File類型的<br />//所以通過isFormField()方法就可以很明確的判斷出所提交的表單,到底是不是一個檔案類型。通過該方法就可以將兩種類型截然的分開<br />/***************【FileItem.getName()方法和上傳同名檔案的衝突問題】**********************************************/<br />//只有當item為File類型時,調用getName()方法才會返回真正的檔案名稱字,如果是普通的表單類型的話,調用getName()就會返回null<br />//另外,由於不同的瀏覽器解析檔案地址的時候採取的方式不同,有的瀏覽器會自動在檔案名稱的前面添加路徑,而有的瀏覽器則只取得檔案名稱<br />//所以就需要我們對獲得的檔案名稱進行手工截取,最後取得的只是檔案的名字,而不包含路徑,這樣最後得到的FileName才是真正的檔案名稱<br />//注意,這裡對擷取的檔案名稱的處理非常重要<br />//為了避免不同使用者上傳相同檔案而導致檔案覆蓋,我們可以在這裡將FileName時間化,即在FileName前面加上new Date().getTime()<br />//這樣儲存在伺服器上的就是以時間毫秒數開頭的檔案了,避免了檔案的同名現象<br />//另外也可以使用隨機數,但是需要我們自己來設定隨機演算法,並且隨機數在計算時,比較耗記憶體<br />//所以當前最常用的就是使用時間來標識上傳的檔案<br />/***************【直接調用FileItem介面的write()方法便可以替代以下操作】*****************************************/<br />//OutputStream os = new FileOutputStream(new File(path, fileName));<br />//InputStream is = item.getInputStream();<br />//byte[] buffer = new byte[400];<br />//int length = 0;<br />//while ((length = is.read(buffer)) > 0) {<br />//os.write(buffer, 0, length);<br />//}<br />//os.close();<br />//is.close();<br />/********************************************************************************************************/
當檔案上傳成功時,會儲存在本地硬碟中
即LocalDisk//tomcat6//webapps//upload//uploadFile//檔案夾中