文件上传
多数文件上传都是通过表单形式提交给后台服务器的,因此,要实现文件上传功能,就需要提供一个文件上传的表单,而该表单必须满足以下3个条件:
<form action="uploadUrl" method="post" enctype="multipart/form-data">
<input type="file" name="filename" multiple="multiple" />
<input type="submit" value="文件上传" />
</form>
当form表单的enctype属性为multipart/form-data时,浏览器就会采用二进制流来处理表单数据,服务器端就会对文件上传的请求进行解析处理。Spring MVC通过MultipartResolver实现文件上传功能。MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipartResolver来完成文件上传工作。MultipartResolver配置示例如下:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置请求编码格式,必须与JSP中的pageEncoding属性一致,默认为ISO-8859-1-->
<property name="defaultEncoding" value="UTF-8" />
<!--设置允许上传文件的最大值(2M),单位为字节-->
<property name="maxUploadSize" value="2097152" />
...
</bean>
在前面的配置代码中,除配置了CommonsMultipartResolver类外,还通过元素配置了编码格式以及允许上传文件的大小。通过元素可以对文件解析器类CommonsMultipartResolver的如下属性进行配置:
注意点: 因为MultipartResolver接口的实现类CommonsMultipartResolver内部是引用multipartResolver字符串获取该实现类对象并完成文件解析的,所以在配置CommonsMultipartResolver时必须指定该Bean的id为multipartResolver。
由于CommonsMultipartResolver是Spring MVC内部通过Apache Commons FileUpload技术实现的,所以Spirng MVC的文件上传还需要依赖Apache Commons FileUpload的组件,即需要导入支持文件上传的相关JAR包。下载地址:单击前往
代码实现
第一步,最基本的添加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">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
第二步:添加springmvc-config.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 定义组件扫描器,指定需要扫描的包 -->
<context:component-scan base-package="com.lzq.controller" />
<!--配置注解驱动 -->
<mvc:annotation-driven />
<!-- 定义视图解析器 -->
<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>
第三步,在前面当中对com.lza.controller包进行扫描,定义一个对应的包,在包中添加Controller类,代码当中表示获取到上传的文件,并且对文件进行重命名。
package com.lzq.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) {
System.out.println("name = "+name);
if (!uploadfile.isEmpty() && uploadfile.size() > 0) {
// 循环输出上传的文件
for (MultipartFile file : uploadfile) {
String filename = file.getOriginalFilename();
String DirPath = request.getServletContext().getRealPath("/upload/");
File filepath = new File(DirPath);
// 地址不存在先创建
if (!filepath.exists()) {
filepath.mkdir();
}
String newFilename = name+ "_"+ UUID.randomUUID() +"_"+filename;
try {
file.transferTo(new File(DirPath + newFilename));
} catch (Exception e) {
e.printStackTrace();
return "error";
}
}
return "success";
}else {
return "error";
}
}
}
第四步,上传文件的jsp页面,在WebContext下。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>
第五步,在WEB-INF下新建一个jsp文件夹,里面添加success.jsp与error.jsp文件,文件内容自定义
运行项目,查看效果:
上传的文件可以在下面的路径当中查看,
项目的工作区间的\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\SpringFileUpLoad\upload
下进行查看
文件下载
在原先的基础上添加一个a标签,使用链接指向Controller控制器类,在类当中编写方法。
先添加标签,直接传递一个参数,带上文件名1.jpg,所以需要提前在文件下新增一个文件。
<a href="${pageContext.request.contextPath }/download?filename=1.jpg">
文件下载 </a>
添加java代码;
@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);
//使用ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.OK);
}
直接运行项目,点击超链接。
在这里就会有一个问题,那就是在进行下载的时候只能使用英文和数字组成的文件,而要下载以中文命令的文件该怎么办呢?
为了解决浏览器中文件下载时中文名称的乱码问题,可以在前端页面发送请求前先对中文名进行统一编码,然后在后台控制器类中对文件名称进行相应的转码,其具体实现步骤如下
壁纸.jpg
的文件。<%@page import="java.net.URLEncoder"%>
。。。。中间省略
<a
href="${pageContext.request.contextPath }/download
?filename <%=URLEncoder.encode("壁纸 .jpg" , "UTF-8")%>">
文件下载 </a>
//根据浏览器的不同进行编码设置.返回编码的文件名
private String getFilename(HttpServletRequest request, String filename)throws Exception {
//ie
String [] IE = {"MSIE","Trident","Edge"};
//获取请求头信息
String userAgent = request.getHeader("User-Agent");
for (String keyword : IE) {
if (userAgent.contains(keyword)) {
return URLEncoder.encode(filename,"UTF-8");
}
}
//火狐等其他浏览器
return new String (filename.getBytes("UTF-8"),"ISO-8859-1");
}