Servlet 3 文件上传 - @MultipartConfig,部分
今天,我们将使用@MultipartConfig注释和来研究 Servlet 3 文件上传示例javax.servlet.http.Part
。前段时间,我写了一篇关于Servlet 文件上传的文章,我使用了 Apache FileUpload API,但在这里我们将使用 Servlet 3 文件上传功能。
Servlet 3 文件上传
由于文件上传是 Web 应用程序中的常见任务,Servlet Specs 3.0 为将文件上传到服务器提供了额外的支持,我们不必依赖任何第三方 API。在本教程中,我们将了解如何使用 Servlet 3.0 API 将文件上传到服务器。
多部分配置
我们需要使用 MultipartConfig 注释来注释文件上传处理程序 servlet,以处理用于将文件上传到服务器的 multipart/form-data 请求。MultipartConfig 注释具有以下属性:
- fileSizeThreshold:我们可以指定文件写入磁盘的大小阈值。大小值以字节为单位,因此 1024*1024*10 为 10 MB。
- location:默认存储文件的目录,默认值为“”。
- maxFileSize:允许上传文件的最大大小,其值以字节为单位。其默认值为 -1L,表示无限制。
- maxRequestSize:multipart/form-data 请求允许的最大大小。默认值为 -1L,表示无限制。
在Java 注释教程中阅读有关注释的更多信息。
零件接口
Part接口表示在 multipart/form-data POST 请求中收到的部分或表单项。一些重要的方法是getInputStream()
,write(String fileName)
我们可以使用这些方法来读取和写入文件。
HttpServletRequest 变更
添加了新方法,HttpServletRequest
以便通过方法获取 multipart/form-data 请求中的所有部分getParts()
。我们可以使用方法获取特定部分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 {
// gets absolute path of the web application
String applicationPath = request.getServletContext().getRealPath("");
// constructs path of the directory to save uploaded file
String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
// creates the save directory if it does not exists
File fileSaveDir = new File(uploadFilePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdirs();
}
System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
String fileName = null;
//Get all the parts from request and write it to the file on server
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
一旦文件成功上传到服务器,就会将一个简单的 JSP 页面作为响应发送给客户端。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>
部署描述符
web.xml 文件中没有用于 servlet 文件上传的新内容,它仅用于将 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>
现在,当我们运行应用程序时,我们会得到以下页面作为响应。日志将显示文件保存的目录位置和内容处置标头信息。
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"
我通过 Eclipse 运行 Tomcat,因此文件位置是这样的。如果您通过命令行运行 tomcat 并通过将 WAR 文件导出到 webapps 目录来部署应用程序,您将获得不同的结构,但结构很清晰。
下载 Servlet 3 多部分文件上传项目