Servlet 3文件上传– @MultipartConfig

时间:2020-02-23 14:41:52  来源:igfitidea点击:

今天,我们将使用@MultipartConfig批注和javax.servlet.http.Part查看Servlet 3文件上传示例。

Servlet 3文件上传

由于文件上传是Web应用程序中的常见任务,因此Servlet Specs 3.0为将文件上传到服务器提供了另外的支持,因此我们不必依赖任何第三方API。
在本教程中,我们将看到如何使用Servlet 3.0 API将文件上传到服务器。

MultipartConfig

我们需要使用MultipartConfig注释对File Upload处理程序servlet进行注释,以处理用于将文件上传到服务器的multipart/form-data请求。
MultipartConfig批注具有以下属性:

  • fileSizeThreshold:我们可以指定大小阈值,之后将文件写入磁盘。
    大小值以字节为单位,因此1024 * 1024 * 10为10 MB。

  • location:默认情况下文件存储的目录,默认值为""。

  • maxFileSize:允许上传文件的最大大小,其值以字节为单位。
    默认值为-1L表示无限制。

  • maxRequestSize:多部分/表单数据请求允许的最大大小。
    默认值为-1L,表示无限制。

在Java Annotations Tutorial中阅读有关注释的更多信息。

零件界面

零件接口表示在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.theitroad.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/hyman/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目录中来部署应用程序,则会得到不同的结构,但结构清晰。