如下内容,是我在课堂做得笔记。总结出来的!!!
1、文件上传的概述
文件上传是项目开发中最常见的功能之一 。
如果要使用文件上传,必须要有如下东西:
- 要有一个
form
标签,method=post
请求; form
标签的encType
属性值必须为multipart/form-data
值;- 在
form
标签中使用<input type=file />
添加上传的文件;
2、文件上传,HTTP 协议的说明
Content-Type: multipart/form-data; boundary=----XXXXXX
- Content-Type:表示提交的数据类型
- multipart/form-data:表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
- boundary:表示每段数据的分隔符,----XXXXXX是由浏览器每次都随机生成。它就是每段数据的分界符。
3、文件上传的使用
文件上传可以在servlet、SpringMVC、SpringBoot中使用。
使用之前先导入两个 jar 包
或者Maven依赖
<!--引入commons-fileUpload-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
3.1 在 servlet 中使用文件上传
在commons-fileupload.jar 和 commons-io.jar 包中,我们涉及到的API有哪些?
ServletFileUpload
类,用于解析上传的数据
FileItem
类,表示每一个表单项
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request)
:判断当前上传的数据格式是否是多段的格式。publicList<FileItem>parseRequest(HttpServletRequestrequest)
:解析上传的数据boolean FileItem.isFormField()
:判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。- true 表示普通类型的表单项
- false 表示上传的文件类型
String FileItem.getFieldName()
:获取表单项的 name 属性值String FileItem.getString()
:获取当前表单项的值。String FileItem.getName()
:获取上传的文件名void FileItem.write( file )
:将上传的文件写到 参数 file 所指向抽硬盘位置 。
前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="uploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username">
<br><br>
头像:<input type="file" name="photo">
<input type="submit" value="上传">
</form>
</body>
</html>
后端代码
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.*;
import java.util.List;
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
// 1 先判断上传的数据是否多段数据(只有多段的数据,才是文件上传的)
if (ServletFileUpload.isMultipartContent(req)) {
// 创建FileItemFactory工厂实现类
FileItemFactory itemFactory = new DiskFileItemFactory();
// 创建用于解析上传数据的工具类ServletFileUpload类
ServletFileUpload upload = new ServletFileUpload(itemFactory);
try {
// 解析上传的数据,得到每一个表单项FileItem
List<FileItem> list = upload.parseRequest(req);
// 循环判断,每一个表单项,是普通类型,还是上传的文件
for (FileItem fileItem : list) {
if (fileItem.isFormField()) {
// 普通类型的表单项
String name = fileItem.getFieldName();
System.out.println("表单项的name属性值:" + name);
String value = fileItem.getString("utf-8");
System.out.println("表单项的value属性值:" + value);
} else {
// 上传的文件
System.out.println("表单项的name属性值:" + fileItem.getFieldName());
// 上传的文件名
String fileName = fileItem.getName();
System.out.println(fileName);
fileItem.write(new File("D:\\IO\\文件上传\\" + fileName));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
3.2 在 SpringMVC 中使用文件上传
Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver
实现的。Spring 用Jakarta Commons FileUpload
技术实现了一个MultipartResolver
实现类:CommonsMultipartResovler
Spring MVC 上下文中默认没有装配MultipartResovler
,因此默认情况下不能处理文件的上传工作,如果想使用Spring 的文件上传功能,需现在上下文中配置MultipartResolver
3.2.1 MultipartFile的常用API
方法名 | 描述 |
---|---|
String getName() | 在多形式返回参数的名称。 |
String getOriginalFilename() | 返回原来的文件名在客户端的文件系统。 |
String getContentType() | 返回的内容类型的文件。 |
boolean isEmpty() | 返回是否上传的文件是空的,也就是说,要么没有文件已在多形式被选定或所选择的文件中没有的内容。 |
long getSize() | 返回以字节为单位的文件的大小。 |
byte[] getBytes() | 返回该文件的内容作为字节数组。 |
InputStream getInputStream() | 返回的InputStream来读取文件的内容。 用户负责关闭该流。 |
void transferTo(File dest) | 接收到的文件转移到给定的目标文件。 |
3.2.2 使用单文件上传,代码如下:
在 spring-mvc.xml 里配置MultipartResolver
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
id="multipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<!-- defaultEncoding: 必须和用户 JSP 的 pageEncoding 属性一致,以便正确解析表单的内容 -->
<property name="maxUploadSize" value="1024000"/>
</bean>
FileUploadController.java
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile;
import java.io.*
import java.util.*;
@Controller
public class FileUploadController {
/**
* 跳转页面
*/
private final String SUCCESS = "success";
/**
* 上传文件最大范围
*/
private final int MAXIMUM_FILE_RANGE = 30000;
/**
* 保存的路径
*/
private final String UPLOAD_DIRECTORY = "D:\\IO";
@RequestMapping("/singleFileUpload")
public String singleFileUpload(Map<String, Object> map,
@RequestParam("file") MultipartFile file,
@RequestParam("desc") String desc) {
// 判断文件是否为空
if (!file.isEmpty()) {
try {
System.out.println(desc);
// 判断文件目录是否存在,否则自动生成
File directory = new File(UPLOAD_DIRECTORY);
// 判断文件或目录是否存在
if (!directory.exists()) {
// 创建一个子目录
directory.mkdirs();
}
// 文件保存路径
String filePath = FilenameUtils.concat(UPLOAD_DIRECTORY, file.getOriginalFilename());
System.out.println(filePath);
// 转存文件
file.transferTo(new File(filePath));
map.put("msg", file.getOriginalFilename());
map.put("date", new SimpleDateFormat("yyyy-MM-dd EEE HH:mm:ss").format(new Date()));
System.out.println(map.get("msg"));
} catch (IOException e) {
e.printStackTrace();
}
}
return SUCCESS;
}
}
upload.jsp
<h2>单文件上传</h2>
<form action="singleFileUpload" method="post" enctype="multipart/form-data">
<p> 选择文件:<input type="file" name="file">
<p> Desc:<input type="text" name="desc"/>
<input type="submit" value="提交">
</form>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传响应页面</title>
</head>
<body>
<h1>文件${msg}上传成功!</h1>
<h2>上传时间为:${date}</h2>
</body>
</html>
运行结果
页面展示:
文件上传成功:
3.2.3 使用多文件上传,代码如下:
在FileUploadController.java里添加以下代码
@RequestMapping("/multipleFileUpload")
public String multipleFileUpload(@RequestParam("files") MultipartFile[] files,
Map<String, Object> map) {
// 判断file数组不能为空并且长度大于0
if (files != null && files.length > 0) {
StringBuilder builder = new StringBuilder();
//循环获取file数组中得文件
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
//失败跳转视图
if (file.getSize() > MAXIMUM_FILE_RANGE) {
map.put("msg", file.getOriginalFilename() + "超过了指定大小");
map.put("flag", "失败");
}
//保存文件
String filePath = FilenameUtils.concat(UPLOAD_DIRECTORY, file.getOriginalFilename());
try {
// 转存文件
file.transferTo(new File(filePath));
builder.append(file.getOriginalFilename() + "、");
} catch (IOException e) {
e.printStackTrace();
}
map.put("msg", Arrays.asList(builder));
map.put("date", new SimpleDateFormat("yyyy-MM-dd EEE HH:mm:ss").format(new Date()));
}
}
return SUCCESS;
}
在upload.jsp里添加以下代码
<h2>多文件上传</h2>
<form action="multipleFileUpload" method="post" enctype="multipart/form-data">
<p> 选择文件:<input type="file" name="files">
<p> 选择文件:<input type="file" name="files">
<p> 选择文件:<input type="file" name="files">
<input type="submit" value="提交">
</form>
运行结果
页面展示:
多文件上传成功:
说明:
前端表单,多个文件组使用同一个 name 名称:files,后台控制器使用@RequestParam("files") MultipartFile[] files
数组来接收。