12.springmvc文件上传
-
Spring MVC 框架的文件上传基于 commons-fileupload 组件,在该组件上做了进一步的封装,简化了文件上传的代码实现,取消了不同上传组件上的编程差异。
-
相对于commons-fileupload原生的上传方式,程序员减少了DiskFileItemFactory,ServletFileUpload和将请求解析为FileItem的工作
-
通过Spring MVC 框架提供的MultipartResolver接口,它为文件上传提供了直接支持,用于处理上传请求,将上传请求包装成可以直接获取文件的数据,从而方便操作。
-
MultpartiResolver 接口有以下两个实现类:
- StandardServletMultipartResolver:使用了 Servlet 3.0 标准的上传方式。
- CommonsMultipartResolver:使用了 Apache 的 commons-fileupload 来完成具体的上传操作。
- MultpartiResolver 接口具有以下方法。
名称 | 作用 |
---|---|
byte[] getBytes() | 以字节数组的形式返回文件的内容 |
String getContentType() | 返回文件的内容类型 |
InputStream getInputStream() | 返回一个InputStream,从中读取文件的内容 |
String getName() | 返回请求参数的名称 |
String getOriginalFillename() | 返回客户端提交的原始文件名称 |
long getSize() | 返回文件的大小,单位为字节 |
boolean isEmpty() | 判断被上传文件是否为空 |
void transferTo(File destination) | 将上传文件保存到目标目录下 |
12.1 单文件上传操作
- 倒入依赖,需要导入 commons-io 和 commons-fileupload,但我们只需要导入commons-fileupload,这个jar包里面集成了 commons-io
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
- 配置 MultipartResolver
<!--文件上传配置-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<!--请求的编码格式,默认为 ISO-8859-1,此处设置为 UTF-8,defaultEncoding 必须和 JSP 中的 pageEncoding 一致,以便正确读取表单的内容-->
<property name="defaultEncoding" value="utf-8"/>
<!--上传文件最大容量100M-->
<property name="maxUploadSize" value="1000480576"/>
<!--内存接收的最大容量-->
<property name="maxInMemorySize" value="51200"/>
</bean>
- 编写文件信息实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FileExp {
private String description;
private CommonsMultipartFile multipartFile;
}
- 编写文件上传控制器
@Controller
@RequestMapping("/file")
public class FileUploadController {
@RequestMapping("/toUploadPage")
public String toUploadPage(){
return "uploadpage";
}
/**
* 把name=file控件的文件封装为一个CommonsMultipartFile对象
* 批量上传CommonsMultipartFile为数组即可
* @ModelAttribute 将对象作为model返回到前端
* */
@RequestMapping("/upload")
public String upload(@ModelAttribute("fileExp") FileExp fileExp, HttpSession session) throws IOException {
String filename = fileExp.getMultipartFile().getOriginalFilename(); //文件名
//若文件名为空则返回到上传页
if (StringUtils.isNullOrEmpty(filename)) {
return "redirect:/file/toUploadPage";
}
String uploadPath = session.getServletContext().getRealPath("/WEB-INF/upload");
File file1 = new File(uploadPath);
if (!file1.exists()) {
file1.mkdirs();
}
//文件输入流
InputStream is = fileExp.getMultipartFile().getInputStream();
//文件输出流
FileOutputStream fos = new FileOutputStream(new File(file1, filename));
byte[] bytes = new byte[1024*1024];
int read = 0;
if ((read = is.read(bytes))!=-1){
fos.write(bytes,0,read);
fos.flush();
}
fos.close();
is.close();
return "result";
}
//采用file.transferTo上传文件
@RequestMapping("/upload2")
public String upload2(@RequestParam("description") String description, @RequestParam("multipartFile") CommonsMultipartFile file, HttpSession session, Model model) throws IOException {
String filename = file.getOriginalFilename(); //文件名
//若文件名为空则返回到上传页
if (StringUtils.isNullOrEmpty(filename)) {
return "redirect:/file/toUploadPage";
}
//上传路径保存设置
String uploadPath = session.getServletContext().getRealPath("/WEB-INF/upload");
File file1 = new File(uploadPath);
if (!file1.exists()) {
file1.mkdirs();
}
file.transferTo(new File(file1,filename));
FileExp fileExp = new FileExp(description, file);
model.addAttribute("fileExp",fileExp);
return "result";
}
}
可以发现有两种方式:
- 一种通过流传输的方式将文件上传
- 另一种是CommonsMultipartFile对象的transferTo()方法,底层也是对流传输的封装。但用起来是方便不少。
- 文件上传表单页面uploadpage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/file/upload2" enctype="multipart/form-data" method="post">
<input type="text" name="description" placeholder="文件描述">
<input type="file" name="multipartFile" placeholder="选择文件">
<input type="submit" value="提交">
</form>
</body>
- 基于表单的文件上传需要使用 enctype 属性,并将它的值设置为 multipart/form-data,使用二进制流来传输文件,同时将表单的提交方式设置为 post。如果不设置默认是application/x-www-form-urlencoded
- 表单的 enctype 属性指定的是表单数据的编码方式,该属性有以下 3 个值。
- application/x-www-form-urlencoded:这是默认的编码方式,它只处理表单域里的 value 属性值。类似get方式将name和value拼接到请求后面。
- multipart/form-data:该编码方式以二进制流的方式来处理表单数据,并将文件域指定文件的内容封装到请求参数里。
- text/plain:该编码方式只有当表单的 action 属性为“mailto:”URL 的形式时才使用,主要适用于直接通过表单发送邮件的方式。
-
另外注意:表单参数和实体类对应问题。
-
结果页面result.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>结果页面</h3>
文件描述:${fileExp.description}
文件名:${fileExp.multipartFile.originalFilename}
</body>
</html>
12.2 多文件上传
- 控制器方法,注意有空文件时,要做文件名为空的处理
//采用file.transferTo上传多文件
@RequestMapping("/upload3")
public String upload3(@ModelAttribute("filesExp") FilesExp filesExp, HttpSession session) throws IOException {
//上传路径保存设置
String uploadPath = session.getServletContext().getRealPath("/WEB-INF/upload");
File file1 = new File(uploadPath);
if (!file1.exists()) {
file1.mkdirs();
}
String filename = "";
//文件
List<CommonsMultipartFile> files = filesExp.getMultipartFile();
for (CommonsMultipartFile file: files) {
filename = file.getOriginalFilename();
if (StringUtils.isNullOrEmpty(filename)) {
return "result2";
}
file.transferTo(new File(file1,filename));
}
return "result2";
}
- 上传页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>多文件上传</title>
</head>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.min.js"></script>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- 可选的Bootstrap主题文件(一般不使用) -->
<%--
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap-theme.min.css"></script>
--%>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<small>多文件上传</small>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/file/upload3" enctype="multipart/form-data" method="post">
<div class="form-group">
<input type="file" class="form-control" name="multipartFile" placeholder="选择文件1">
<input type="text" class="form-control" name="description" placeholder="文件描述1">
</div>
<div class="form-group">
<input type="file" class="form-control" name="multipartFile" placeholder="选择文件2">
<input type="text" class="form-control" name="description" placeholder="文件描述2">
</div>
<div class="form-group">
<input type="file" class="form-control" name="multipartFile" placeholder="选择文件3">
<input type="text" class="form-control" name="description" placeholder="文件描述3">
</div>
<input type="submit" class="btn btn-primary btn-block" value="提交">
</form>
</div>
</body>
</html>
- 结果页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>多文件上传结果显示</title>
</head>
<body>
<h3>结果页面</h3>
<table border="1px">
<thead>
<tr>
<th>文件名</th>
<th>文件描述</th>
</tr>
</thead>
<tbody>
<!-- 同时取两个数组的元素 -->
<c:forEach var="filename" items="${filesExp.multipartFile}" varStatus="status">
<tr>
<td>${filename.originalFilename}</td>
<td>${filesExp.description.get(status.index)}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
下一篇:SpringMVC-20-springmvc文件下载
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123883.html