文件上傳
一、對錶單的一些要求
- 提交方法必須是post:
method="post"
。 - 編碼屬性必須是multipart/form-data,也就是“多組件的表單數據”,即
enctype="multipart/form-data"
。
- 表單中需要添加文件表單項,即
<input type="file" name="xxx" />
。
示例:
<body>
<h1>上傳1</h1>
<form action="<c:url value='/Upload1Servlet'/>" method="post" enctype="multipart/form-data">
用戶名:<input type="text" name="username" /><br>
照片:<input type="file" name="zhaopian" /><br>
<input type="submit" value="上傳" />
</form>
</body>
二、對servlet的一些要求
我們回憶一下我們以前用來接收表單傳遞過來的參數,使用的request.getParameter("xxx")
,而這個方法在表單爲enctype="multipart/form-data"
時,就作廢了。它永遠都會返回null。
那麼我們應該使用什麼樣的方法呢?是request.getInputStream()
,返回值爲ServletInputStream
類型,它會包含整個請求的體。
接下來我們研究一下多部件表單的體。
三、多部件表單請求體
- 分隔出多個部件,即一個表單項一個部件。
- 一個部件中自己包含請求頭和空行,以及請求體。
- 普通表單項:
只有一個頭:Content-Disposition:包含name=“xxxx”,即表單項名稱。
體就是表單項的值
。 - 文件表單項:
有兩個頭:
Content-Disposition
:包含name="xxxx"
,即表單項名稱;還有一個filename="xxx"
,表示上傳文件的名稱
Content-Type
:它是上傳文件的MIME類型,例如:image/pjpeg,表示上傳的是圖片,其中是jpg擴展名的圖片。
體就是上傳文件的內容
。
四、使用servlet獲取表單上傳的數據
我們寫一個相應的Servlet:
public class Upload1Servlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
ServletInputStream in = request.getInputStream();
String s = IOUtils.toString(in);
System.out.println(s);
}
}
然後我們在頁面表單上輸入一些內容,然後在後臺查看會輸出什麼。
後臺內容:
我們可以清楚的看到上傳組件的部分構成。
五、commons-fileupload組件介紹
我們在上面的示例中獲取了表單上傳的數據,但是明顯的是,我們上傳的是一張圖片,後臺顯示出來的是一堆字符亂碼,這顯然是沒用的,我們就要想辦法把它變成圖片,這個時候應該怎麼做呢?
我們通過觀察,可以發現,請求體是有一定的固定格式的,我們很容易聯想到我們採取字符串分割一步步得到我們想要的內容,但是這樣有點太過於麻煩,這個時候我們應該怎麼辦呢?其實Apache已經幫我們提供瞭解析它的工具:commons-fileupload。
fileupload是由apache的commons組件提供的上傳組件。它最主要的工作就是幫我們解析request.getInputStream()
。
fileupload組件需要的JAR包有:
- commons-fileupload.jar,核心包;
- commons-io.jar,依賴包。
這個小組件,它會幫我們解析request中的上傳數據,解析後的結果是一個表單項數據封裝到一個FileItem
對象中。我們只需要調用FileItem的方法即可!
fileupload的核心類有:DiskFileItemFactory
、ServletFileUpload
、FileItem
。
使用fileupload組件的步驟如下:
1). 創建工廠類DiskFileItemFactory對象:DiskFileItemFactory factory = new DiskFileItemFactory();
2). 使用工廠創建解析器對象:ServletFileUpload fileUpload = new ServletFileUpload(factory);
3). 使用解析器來解析request對象:List<FileItem> list = fileUpload.parseRequest(request);
我們重點介紹一下FileItem
類。一個FileItem對象對應一個表單項(表單字段)。一個表單中存在文件字段和普通字段,可以使用FileItem類的isFormField()
方法來判斷表單字段是否爲普通字段,如果不是普通字段,那麼就是文件字段了。
String getName()
:獲取文件字段的文件名稱;String getString()
:獲取字段的內容,如果是文件字段,那麼獲取的是文件內容,當然上傳的文件必須是文本文件;String getFieldName()
:獲取字段名稱,例如:<input type=”text” name=”username”/>
,返回的是username;String getContentType()
:獲取上傳的文件的類型,例如:text/plain。int getSize()
:獲取上傳文件的大小;boolean isFormField()
:判斷當前表單字段是否爲普通文本字段,如果返回false,說明是文件字段;InputStream getInputStream()
:獲取上傳文件對應的輸入流;void write(File)
:把上傳的文件保存到指定文件中。
六、上傳的實例
接下來我們寫一下上傳的示例。
首先新建一個jsp,放入一個表單:
<body>
<h1>上傳2</h1>
<form action="<c:url value='/Upload2Servlet'/>" method="post" enctype="multipart/form-data">
用戶名:<input type="text" name="username" /><br>
照片:<input type="file" name="zhaopian" /><br>
<input type="submit" value="上傳" />
</form>
</body>
接下來是我們的servlet:
public class Upload2Servlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
/*
* 上傳的三步:
* 1.創建工廠類;
* 2.通過工廠類創建解析器;
* 3.解析request,得到FileItem集合
* 4.遍歷FileItem集合,調用其API完成文件的保存
*/
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
try {
List<FileItem> fileItemList = sfu.parseRequest(request);
FileItem fi1 = fileItemList.get(0);
FileItem fi2 = fileItemList.get(1);
System.out.println("普通表單項演示:" + fi1.getFieldName() + "="
+ fi1.getString("UTF-8"));
System.out.println("文件表單項演示:");
System.out.println("Content-Type:" + fi2.getContentType());
System.out.println("size:" + fi2.getSize());
System.out.println("filename:" + fi2.getName());
// 保存文件
File destFile = new File("E:/test.jpg");
fi2.write(destFile);
} catch (FileUploadException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
我們在瀏覽器中打開網頁,並且選擇一張圖片:
我們看一下後臺出現了什麼:
我們再看一下我們的E盤下有沒有出現一個新的文件:
我們發現,功能全部符合我們的預期。
下一步,我們就要研究一下文件上傳中的一些其他的細節問題。
END.