JavaWeb 文件上传功能
1. 获取 Port 接口的集合
在Servlet3.0中,新增了Part 接口,可以方便的进行文件上传处理,可以通过 HttpServletRequest 对象的 getPart()
方法取得Part实现对象。
/** 源码
* This class represents a part as uploaded to the server as part of a
* <code>multipart/form-data</code> request body. The part may represent either
* an uploaded file or form data.
*
* @since Servlet 3.0
*/
public interface Part {......}
/**1. 获取 Port 接口的集合
* Part 接口:用于上传文件到服务器
* getParts() 方法:获取元素为 Part 接口的集合
* 页面请求的数据被封装到request域中的Part属性中
* */
Collection<Part> parts = req.getParts();
2. 添加 @MultipartConfig 标注
在 Tomat 中要在 Servlet 上设置 @MultipartConfig 才能取得 Part 对象,否则 getPart() 会得到 null 结果。
@MultipartConfig 标注可用来设置 Servlet 处理上传文件的相关信息,如果没有设置属性则取默认值。
可用属性如下表
fileSizeThreshold | 整数值,文件缓存的临界点,超过则先保存到临时目录,即缓存文件,默认值为0 |
---|---|
location | 字符串,写入文件时的目录,如果设置这个属性值,则缓存文件就是写到指定的目录,也可搭配 Part的 write() 方法使用,默认为空字符串 |
maxFileSize | 限制上传文件大小,默认值为 -1L,表示无限制 |
maxRequestSize | 限制 multipart/form-data 请求个数,默认值为-1L,表示不限制个数 |
@MultipartConfig
public class Upload extends HttpServlet{......}
3. 在服务器中创建目录 /upload
/**3. 在服务器中创建存放上传文件的文件夹 /upload
* 如果目录 /upload 不存的话,就通过File类的创建方法创建
* */
String realPath = req.getServletContext().getRealPath("/upload"); //getServletContext().getRealPath() 也可以获取不存在的路径,返回的结果是一个拼成的路径
System.out.println(realPath);
boolean mkdirs = new File(realPath).mkdirs(); //将通过 ServletContext 域对象的 getRealPath() 方法获取的拼接路径,通过File类和mkdirs()方法创建出来
4. 遍历元素 Part 获取各自对应的头信息
/**4. 遍历元素 Part 获取各自对应的头信息
* 调用元素 Part 接口的 getHeader() 方法,获取前端form表单提交过来的头的详细信息
* 表单提交的头信息:
* 在Mac系统中的表单提交的头(enctype="multipart/form-data")的信息
------WebKitFormBoundaryw8aYcJlpgDXW7UpK
Content-Disposition: form-data; name="filenameSingle"; filename="配置.txt"
Content-Type: text/plain
------WebKitFormBoundaryw8aYcJlpgDXW7UpK--
* */
for (Part part : parts) {
String header = part.getHeader("Content-Disposition");
String filename = getFileName(header); // 调用外界方法,获取字符串中的filename子字符串
if (null!=filename&&!"".equals(filename)) {//防止上传空文件
/**5. 执行上传
* 调用Part接口的write("upload路径"+"文件名")方法,上传到服务器的目录
* */
part.write(realPath+"/"+filename);
}
}
5. 执行上传
if (null!=filename&&!"".equals(filename)) {//防止上传空文件,注意,这里比较空字符串不要用!=,否则会无法比较
/**5. 执行上传
* 调用Part接口的write("upload路径"+"文件名")方法,上传到服务器的目录
* */
part.write(realPath+"/"+filename);
}
功能实现代码
Java 代码 - /demo/src/com/Upload.java
package com;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
/**2. 添加 @MultipartConfig 标注
*/
@MultipartConfig
public class Upload extends HttpServlet{
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
/**1. 获取 Port 接口的集合
* Part 接口:用于上传文件到服务器
* getParts() 方法:获取元素为 Part 接口的集合
* */
Collection<Part> parts = req.getParts();
/**3. 在服务器中创建存放上传文件的文件夹 /upload
* 如果目录 /upload 不存的话,就通过File类的创建方法创建
* */
String realPath = req.getServletContext().getRealPath("/upload"); //getServletContext().getRealPath() 也可以获取不存在的路径,返回的结果是一个拼成的路径
System.out.println(realPath);
boolean mkdirs = new File(realPath).mkdirs(); //将通过 ServletContext 域对象的 getRealPath() 方法获取的拼接路径,通过File类和mkdirs()方法创建出来
/**4. 遍历元素 Part 获取各自对应的头信息
* 调用元素 Part 接口的 getHeader() 方法,获取前端form表单提交过来的头的详细信息
* 表单提交的头信息:
* 在Mac系统中的表单提交的头(enctype="multipart/form-data")的信息
------WebKitFormBoundaryw8aYcJlpgDXW7UpK
Content-Disposition: form-data; name="filenameSingle"; filename="配置.txt"
Content-Type: text/plain
------WebKitFormBoundaryw8aYcJlpgDXW7UpK--
*/
for (Part part : parts) {
String header = part.getHeader("Content-Disposition");
String filename = getFileName(header); // 调用外界方法,获取字符串中的filename子字符串
if (null!=filename&&!"".equals(filename)) {//防止上传空文件
/**5. 执行上传
* 调用Part接口的write("upload路径"+"文件名")方法,上传到服务器的目录
*/
part.write(realPath+"/"+filename);
}
}
resp.getWriter().write("<h1>上传成功</h1>");
}
//防止恶意访问
public String getFileName(String header) {
if(header!=null) {
String[] split = header.split("=");
String string = split[split.length-1];
String replace = string.replace("\"", "");
return replace;
}else {
return null;
}
}
@Override
public void destroy() {
super.destroy();
}
}
前端页面 jsp 代码 - /demo/WebContent/download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<!-- enctype 属性:规定在发送到服务器之前应该如何对表单数据进行编码。
application/x-www-form-urlencoded : 默认编码,但不支持于文件上传在发送到服务器之前,
使用此属性,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)
multipart/form-data : 设置表单的MIME(多用途互联网邮件扩展类型)编码
注意:
在Mac系统中的表单提交的头(enctype="multipart/form-data")的信息
------WebKitFormBoundaryw8aYcJlpgDXW7UpK
Content-Disposition: form-data; name="filenameSingle"; filename="配置.txt"
Content-Type: text/plain
------WebKitFormBoundaryw8aYcJlpgDXW7UpK--
-->
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="filenameSingle" />单文件<br/>
<input type="file" name="filenameMultiple" multiple="multiple"/>多文件<br/>
<input type="submit" value="upload">
</form>
</body>
</html>
web.xml - /demo/WebContent/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>demo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>ServletContextName</param-name>
<param-value>ServletContextValue</param-value>
</context-param>
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.Upload</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
</web-app>
![15580222-40fb523b85422e44.png](https://i-blog.csdnimg.cn/blog_migrate/c77bd11a2eb13ee1c053ad95bbb86f87.webp?x-image-process=image/format,png)
上传成功,打印上传到的目录
![15580222-f6fffed6c5fcadea.png](https://i-blog.csdnimg.cn/blog_migrate/d318ada524e0676c2174016ce77f41c8.webp?x-image-process=image/format,png)
表单提交的头信息