今天我們將介紹使用@MultipartConfig註釋和javax.servlet.http.Part
的Servlet 3文件上傳示例。不久前,我寫了一篇關於Servlet文件上傳的文章,並使用了Apache FileUpload API,但在這裡我們將使用Servlet 3文件上傳功能。
Servlet 3文件上傳
由於文件上傳是Web應用程序中常見的任務,Servlet規範3.0提供了額外的支持,用於將文件上傳到服務器,我們不需要依賴任何第三方API來實現這一功能。在本教程中,我們將看到如何使用Servlet 3.0 API將文件上傳到服務器。
MultipartConfig
我們需要使用MultipartConfig註釋來標註文件上傳處理servlet,以處理multipart/form-data請求,該請求用於將文件上傳到服務器。MultipartConfig註釋具有以下屬性:
- fileSizeThreshold:我們可以指定文件寫入磁盤之前的大小閾值。大小值以字節為單位,因此1024*1024*10表示10 MB。
- 位置:文件将默认存储的目录,其默认值为“”。
- maxFileSize:允许上传文件的最大大小,其值以字节为单位提供。其默认值为-1L,表示无限制。
- maxRequestSize:multipart/form-data请求允许的最大大小。默认值为-1L,表示无限制。
了解更多关于注解的内容,请参考Java注解教程。
Part接口
Part 接口表示在multipart/form-data POST请求中接收到的一个部分或表单项。一些重要的方法是getInputStream()
和write(String fileName)
,我们可以用它们来读取和写入文件。
HttpServletRequest变更
HttpServletRequest
中新增了getParts()
方法,用于获取multipart/form-data请求中的所有部分。我们可以使用getPart(String partName)
方法获取特定的部分。让我们看一个简单的项目,我们将使用上述API方法来使用servlet上传文件。我们的项目结构如下图所示。
HTML表单
我们有一个简单的HTML页面,我们可以选择要上传的文件并提交请求到服务器进行上传。index.html
<html>
<head></head>
<body>
<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
Select File to Upload:<input type="file" name="fileName">
<br>
<input type="submit" value="Upload">
</form>
</body>
</html>
文件上传Servlet
这是我们的文件上传Servlet实现。FileUploadServlet.java
package com.journaldev.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/FileUploadServlet")
@MultipartConfig(fileSizeThreshold=1024*1024*10, // 10 MB
maxFileSize=1024*1024*50, // 50 MB
maxRequestSize=1024*1024*100) // 100 MB
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 205242440643911308L;
/**
* Directory where uploaded files will be saved, its relative to
* the web application directory.
*/
private static final String UPLOAD_DIR = "uploads";
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 获取Web应用程序的绝对路径
String applicationPath = request.getServletContext().getRealPath("");
// 构建保存上传文件的目录路径
String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
// 如果目录不存在,则创建保存目录
File fileSaveDir = new File(uploadFilePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdirs();
}
System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
String fileName = null;
// 从请求中获取所有部分并将其写入服务器上的文件中
for (Part part : request.getParts()) {
fileName = getFileName(part);
part.write(uploadFilePath + File.separator + fileName);
}
request.setAttribute("message", fileName + " File uploaded successfully!");
getServletContext().getRequestDispatcher("/response.jsp").forward(
request, response);
}
/**
* Utility method to get file name from HTTP header content-disposition
*/
private String getFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
System.out.println("content-disposition header= "+contentDisp);
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf("=") + 2, token.length()-1);
}
}
return "";
}
}
請注意使用@MultipartConfig註釋以指定上傳文件的不同大小參數。我們需要使用請求標頭”content-disposition”屬性來獲取客戶端發送的文件名,並將文件保存為相同的名稱。目錄位置是相對於我保存文件的Web應用程序,您可以將其配置到其他位置,例如在Apache Commons FileUpload示例中。
響應JSP
A simple JSP page that will be sent as response to client once the file is uploaded successfully to server. response.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Upload File Response</title>
</head>
<body>
<%-- Using JSP EL to get message attribute value from request scope --%>
<h2>${requestScope.message}</h2>
</body>
</html>
部署描述符
對於Servlet文件上傳,web.xml文件中沒有新的內容,它僅用於將index.html設置為歡迎文件。 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ServletFileUploadExample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
現在,當我們運行應用程序時,我們會得到以下響應頁面。
日誌將顯示文件保存的目錄位置和content-disposition標頭信息。
Upload File Directory=/Users/pankaj/Documents/workspace/j2ee/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ServletFileUploadExample/uploads
content-disposition header= form-data; name="fileName"; filename="IMG_2046.jpg"
I am running Tomcat through Eclipse, that’s why file location is like this. If you run tomcat through command line and deploy application by exporting as WAR file into webapps directory, you will get different structure but a clear one.
Source:
https://www.digitalocean.com/community/tutorials/servlet-3-file-upload-multipartconfig-part