1 文件上传概述
多数文件都是通过表单形式提交给后台服务器的,实现文件上传功能就需要一个表单,需要满足如下三个条件:
- form表单的method属性设置为post
- form表单的enctype属性设置为multipart/form-data
- 提供
<input type="file" name="filename">
的文件上传输入框
![](https://img-blog.csdnimg.cn/20200903211826786.png#pic_center)
当form表单的enctype属性为multipart/form-data时,浏览器就会采用二进制流来处理表单数据,服务器端就会对文件上传的请求进行解析处理,Spring MVC通过MultipartResolver实现文件上传功能。这是一个接口对象,需要通过它的实现类CommonsMultipartResolver来完成文件上传功能。在springmvc-config.xml中配置如下:
![](https://img-blog.csdnimg.cn/20200903212332332.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hhYV9f,size_16,color_FFFFFF,t_70#pic_center)
注意:因为MultipartResolver接口的实现类CommonsMultipartResolver内部是引用multipartResolver字符串获取该实现类对象并完成文件解析的,所以在配置CommonsMultipartResolver时必须指定该Bean的id为multipartResolver。
MultipartResolver可以配置的属性有:
![](https://img-blog.csdnimg.cn/20200903212434371.png#pic_center)
由于CommonsMultipartResolver是Spring MVC内部通过ApacheCommons FileUpload技术实现的,所以Spirng MVC的文件上传还需要依赖ApacheCommons FileUpload的组件,即需要导入支持文件上传的相关JAR包。
- commons-fileupload-1.3.2.jar
- commons-io-2.5.jar
1.1 代码实现
- pom.xml添加依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
- springmvc-config.xml中配置MultipartResolver
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置请求编码格式 -->
<property name="defaultEncoding" value="UTF-8" />
</bean>
- FileUploadController.java
package cn.edu.ujn.ch16.controller;
import java.io.File;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
/*
文件上传
*/
@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 {
// 使用MultipartFile接口的方法完成上传文件到指定位置
file.transferTo(new File(dirPath + newFilename));
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return "error";
}
}
// 跳转到成功页面
return "success";
} else {
return "error";
}
}
}
- fileUpload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传</title>
<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>
2 文件下载
文件下载就是将文件服务器中的文件下载到本机,在Spring MVC环境中,实现文件下载分为两个步骤:
- 在客户端页面使用一个文件下载的超链接,该链接的herf属性要指定后台文件下载的方法及文件名(需要现在文件下载目录中添加一个名为“1.jpg”的文件)
![](https://img-blog.csdnimg.cn/20200904095423921.png#pic_center)
2.1 中文名文件下载
- 在下载页面中对中文文件名编码,可以收用Servlet API中URLEncoder.encoder(String s,String enc)方法将中文转为UTF-8编码
download.jsp如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page import="java.net.URLEncoder"%>
<%@ page isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>下载页面</title>
</head>
<body>
<%-- <a href="${pageContext.request.contextPath }/download?filename=1.jpg">
文件下载
</a> --%>
<a href="${pageContext.request.contextPath }/download?filename=<%=URLEncoder.encode("壁纸.jpg", "UTF-8")%>">
中文名称文件下载
</a>
</body>
</html>
- 在控制器类中编写对中文名文件下载时进行转码编码的方法:
/**
* 根据浏览器的不同进行编码设置,返回编码后的文件名
*/
public String getFilename(HttpServletRequest request, String filename) throws Exception {
// IE不同版本User-Agent中出现的关键词
String[] IEBrowserKeyWords = { "MSIE", "Trident", "Edge" };
// 获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
// 对不同浏览器进行不同格式的转码
for (String keyWord : IEBrowserKeyWords) {
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");
}
2.2 代码实现
配置文件同文件上传,在控制器类中添加如下方法:
// 文件下载
@RequestMapping("/download")
// ResponseEntuty对象类似于@ResponseBody注解,用于直接返回结果对象
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);
// MediaType代表的是Internet Media
// Type(即互联网媒体类型),MediaType.APPLICATION_OCTET_STREAM的值为application/octet-stream,即表示以二进制流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 使用Sring MVC框架的ResponseEntity对象封装返回下载数据
// HttpStatus.OK 表示200,即服务器已成功处理了请求
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);
}
/**
* 根据浏览器的不同进行编码设置,返回编码后的文件名
*/
public String getFilename(HttpServletRequest request, String filename) throws Exception {
// IE不同版本User-Agent中出现的关键词
String[] IEBrowserKeyWords = { "MSIE", "Trident", "Edge" };
// 获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
// 对不同浏览器进行不同格式的转码
for (String keyWord : IEBrowserKeyWords) {
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");
}
声明:
本篇文章为学习笔记,若作品涉及版权或存在其他问题,请联系我删除。
谢谢浏览!