版本:idea2020.1.1 jdk1.8 maven3.6.3
注:本文章摘自Java EE企业级应用开发教程,黑马程序员/编著,仅用于记录学习笔记,分享学习经历。
Tomcat配置参考:https://mp.csdn.net/editor/html/114296147
一、文件上传
1、文件上传概述
实现文件上传,必须提供一个满足三个条件的表单,三个条件如下:
method属性必须是post、enctype属性必须为multipart/form-data、<input type="file" name="filename"/>
<form action="uploadUrl" method="post" enctype="multipart/form-data">
<input type="file" name="filename" multiple="multiple"/>
<input type="submit" value="文件上传"/>
</form>
multiple:是HTML5的新属性,实现多文件上传。
当客户端form表单的enctype属性为multipart/form-data时,浏览器就会采用二进制流的方式来处理表单数据,服务器端就会对文件上传的请求进行解析处理。Spring MVC为文件上传提供了直接的支持,这种支持是通过MultipartResolver(多部件解析器)对象实现的。MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipartResolver来完成文件上传工作。
springmvc-config.xml文件
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置请求编码格式,必须与JSP中的pageEncoding属性一致,默认为ISO-8859-1-->
<property name="defaultEncoding" value="UTF-8"/>
<!--设置允许上传文件的最大值2mb,单位为字节-->
<property name="maxUploadSize" value="2097152"/>
...
</bean>
属性 | 说明 |
---|---|
maxUploadSize | 上传文件最大长度,以字节为单位 |
maxInMemorySize | 缓存中的最大尺寸 |
defaultEncoding | 默认编码格式 |
resolveLazyily | 推迟文件解析,以便在Controller中捕获文件大小异常 |
Controller类方法
@RequestMapping("/fileUpload")
public String handleFormUpload(@RequestParam("name") String name, @RequestParam("filename")MultipartFile file,...) {
if (!file.isEmpty()) {
//具体执行方法
...
return "uploadSuccess";
}
return "uploadFailure";
}
上传到程序中的文件被封装到org.springframework.web.multipart.MultipartFile接口中
方法 | 说明 |
---|---|
byte[] getBytes() | 以字节数组的形式返回文件的内容 |
String getContentType() | 返回文件的内容类型 |
InputStream getInputStream() | 读取文件内容,返回一个InputStream流 |
String getName() | 获取多部件form表单的参数名称 |
String getOriginalFilename() | 获取上传文件的初始化名 |
long getSIze() | 获取上传文件的大小,单位是字节 |
boolean isEmpty() | 判断上传的文件是否为空 |
void transferTo(FIle file) | 将上传文件保存到目标目录下 |
2、应用案例:
导入maven依赖 ——> 编辑springmvc-config.xml ——> 创建FileUploadController ——> 创建fileUpload.jsp ——> 创建success.jsp和error.jsp ——> 测试
<!--文件上传依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--指定需要扫描的包-->
<context:component-scan base-package="com.jc.controller"/>
<!--定义视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置文件上传解析器MultipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置请求编码格式-->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
</beans>
@Controller
public class FileUploadController {
//执行文件上传
@RequestMapping("/fileUpload")
public String handleFormUpload(@RequestParam("name") String name, @RequestParam("uploadfile") List<MultipartFile> uploadfile, HttpServletRequest request) {
//判断所上传文件是否存在
if (!uploadfile.isEmpty() && uploadfile.size() > 0) {
//循环输出上传的文件
for (MultipartFile file : uploadfile) {
//获取上传文件的原始名称
String originalFilename = file.getOriginalFilename();
//设置上传文件的保存地址目录
String dirPath = request.getServletContext().getRealPath("/upload/");
File filePath = new File(dirPath);
//如果保存文件的地址不存在,就先创建目录
if (!filePath.exists()) {
filePath.mkdirs();
}
//使用UUID重新命名上传文件的名称(上传人_uuid_原始文件名称)
String newFilename = name + "_" + UUID.randomUUID() + "_" + originalFilename;
try {
file.transferTo(new File(dirPath + newFilename));
} catch (IOException e) {
e.printStackTrace();
return "error";
}
}
//跳转到成功页面
return "success";
} else {
return "error";
}
}
}
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/13
Time: 下午 6:02
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>文件上传</title>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
<script>
function check() {
var name = document.getElementById("name").value;
var file = document.getElementById("file").value;
if (name == "") {
alert("填写上传人");
return false;
}
if (file.length == 0 || file == "") {
alert("请选择上传文件");
return false;
}
return true;
}
</script>
</head>
<body>
<form action="${pageContext.request.contextPath }/fileUpload" method="post" enctype="multipart/form-data" onsubmit="return check()">
上传人:<input id="name" type="text" name="name"/><br/>
请选择文件:<input id="file" type="file" name="uploadfile" multiple="multiple"/><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/13
Time: 下午 6:23
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP '' starting page</title>
</head>
<body>
成功 <br>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/13
Time: 下午 6:23
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP '' starting page</title>
</head>
<body>
失败 <br>
</body>
</html>
upload文件夹在项目的发布路径中,而不是创建的项目所在目录。如果未更改项目发布路径,则要去工作空间的metadata目录中寻找项目发布目录(请自行百度)如果将项目的发布路径已更改到tomcat中,则需要在tomcat的webapps目录中寻找。
二、文件下载
1、实现文件下载案例:
(1)在客户端页面使用一个文件下载的超链接,该链接的href属性要指定后台文件下载的方法以及文件名
<a href="${pageContext.request.contextPath }/download?filename=1.jpg">
文件下载</a>
(2)Spring MVC提供了一个ResponseEntity类型的对象,使用它可以很方便地定义返回的HttpHeaders对象和HttpStatus对象,通过这两个对象的设置,即可完成下载文件时所需的配置信息。
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception {
//指定要下载的文件所在路径
String path = request.getServletContext().getRealPath("/upload/");
//创建该文件对象
File file = new File(path+File.separator+filename);
//设置响应头
HttpHeaders headers = new HttpHeaders();
//通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment",filename);
//定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//使用Spring MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);
}
在fileDownload()方法中,首先根据文件路径和需要下载的文件名来创建文件对象,然后对响应头中文件下载时的打开方式以及下载方式进行了设置,最后返回ResponseEntity封装的下载结果对象。ResponseEntity对象有些类似前面的@ResponseBody注解,它用于直接返回结果对象。上面代码中,设置响应头信息中的MediaType代表的是Interner Media Type(互联网媒体类型)也叫做MIME类型,MediaType.APPLICATION_OCTET_STREAM的值为application/cotet-stream,即表示以二进制流的形式下载数据,HttpStatus类型代表的是Http协议中的状态,上面代码中HttpStatus.OK表示200,即服务器已成功处理了请求。
编辑FileUploadController ——> 创建download.jsp
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception {
//指定要下载的文件所在路径
String path = request.getServletContext().getRealPath("/upload/");
//创建该文件对象
File file = new File(path+File.separator+filename);
//设置响应头
HttpHeaders headers = new HttpHeaders();
//通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment",filename);
//定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//使用String MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.OK);
}
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/14
Time: 上午 8:26
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP '' starting page</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/download?filename=1.jpg">
文件下载</a>
</body>
</html>
2、中文名称的文件下载
修改FileUploadController ——> 修改download.jsp
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception {
//指定要下载的文件所在路径
String path = request.getServletContext().getRealPath("/upload/");
//创建该文件对象
File file = new File(path+File.separator+filename);
// 对文件名编码,防止中文文件乱码
filename = this.getFilename(request, filename);
//设置响应头
HttpHeaders headers = new HttpHeaders();
//通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment",filename);
//定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//使用String MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.OK);
}
//根据浏览器不同进行编码设置,返回编码后的文件名
public String getFilename(HttpServletRequest request, String filename) throws Exception {
//ie不同版本User-Agent中出现的关键词
String[] IEBrowseKeyWords = {"MSIE", "Trident", "Edge"};
//获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
for (String keyWord:IEBrowseKeyWords) {
if (userAgent.contains(keyWord)) {
//IE内核浏览器,统一为UTF-8编码显示
return URLEncoder.encode(filename, "UTF-8");
}
}
//火狐等其他浏览器统一为ISO-8859-1编码
return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
}
<%--
Created by IntelliJ IDEA.
User: jiangchao
Date: 2021/4/14
Time: 上午 8:26
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%@ page import="java.net.URLEncoder" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP '' starting page</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/download?filename=<%=URLEncoder.encode("哈哈.jpg","UTF-8")%>">
中文名称文件下载</a>
</body>
</html>