(一)文件上传概述
多数文件上传都是通过表单形式提交给后台服务器,因此要实现文件上传功能就需要提供一个文件上传的表单。表单必须满足以下3个条件:
1. form表单中的method属性设置为post
2.form表单中的enctype属性设置为multipart/form-data
注:multiple="multiple实现多文件上传
3. 提供<input id="file" type="file" name="uploadfile" multiple="multiple" />
1.在springmvc-config.xml中配置CommonsMultipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置文件上传编码-->
<property name="defaultEncoding" value="UTF-8"/>
<!--设置允许上传文件的最大值(2M))-->
<property name="maxUploadSize" value="2097152"/>
<!--设置缓存中的最大值(2M))-->
<property name="maxInMemorySize" value="2097152"/>
<!--设置文件推出解析-->
<property name="resolveLazily" />
</bean>
2.MultipartFile接口的主要方法
方法 | 说明 |
---|---|
String getName() | 获取多部件form表单的参数名 |
String getOriginalFilename() | 获取上传文件名 |
String getContentType() | 获取文件内容类型 |
boolean isEmpty() | 判断上传文件是否为空 |
long getSize() | 获取上传文件的大小 |
byte[] getBytes() | 以字节数组的形式返回文件内容 |
InputStream getInputStream() | 读取问价内容,返回一个InputStream对象 |
void transferTo(File dest) | 将上传文件保存到目标目录 |
(二)文件上传演示
项目结构图:
步骤如下:
1.spring-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.wang" />
<!-- 定义视图解析器 -->
<bean id="viewResolver" class=
"org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 设置前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 设置后缀 -->
<property name="suffix" value=".jsp" />
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置文件上传编码-->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
</beans>
2.fileload.jsp
<%@ 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(){
//通过标签的id属性获取属性值
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/><br/>
请选择文件:<input id="file" type="file" name="uploadfile"
multiple="multiple" /><br/><br/>
<input type="submit" value="上传" />
</form>
</body>
</html>
3.FileIploadController.java
package com.wang;
import java.io.File;
import java.util.ArrayList;
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")
/*必须使用注释 @RequestParam("uploadfile")List<MultipartFile> uploadfile
*否则报Failed to instantiate [java.util.List]: Specified class is an interface错误
* */
public String handleFormUpload(String name, @RequestParam("uploadfile")List<MultipartFile> uploadfile, HttpServletRequest request) {
// 如果上传文件存在
if (!uploadfile.isEmpty() && uploadfile.size() > 0) {
// 遍历文件
for (MultipartFile file : uploadfile) {
// 获取上传文件的名称
String originalFilename = file.getOriginalFilename();
System.out.println("文件名"+originalFilename);
// 设置上传文件保存的地址目录
String dirpath = request.getServletContext().getRealPath("/images");
File filepath = new File(dirpath);
// 如果保存文件的目录不存在,创建upload文件夹
if (!filepath.exists()) {
filepath.mkdirs();
}
// 使用UUID重新命名上传文件的名称
String newFilename = name + "_" + UUID.randomUUID() + "_" + originalFilename;
System.out.println(newFilename);
try {
// 使用MultipartFile的方法将文件上传到指定位置
file.transferTo(new File(dirpath +File.separator+ newFilename));
System.out.println("目标路径"+dirpath +File.separator+ newFilename);
//定义列表保存图片保存的路径
List<String> filenames=new ArrayList<String>();
filenames.add(newFilename);
request.setAttribute("filenames", filenames);
} catch (Exception e) {
e.printStackTrace();
return "error";
}
}
}
return "sucess";
}
}
4.sucess.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>
<h1>文件上传页面</h1>
<form >
<table border="1">
<tr>
<th>图片展示</th>
</tr>
<c:forEach items="${filenames}" var="newfilename">
<!--路径为以下形式,浏览器可以打开图片-->
<td><img alt="" src="/FileDownload/images/${newfilename}" width="140" height="170"/> </td>
</c:forEach>
</table>
</form>
</body>
</html>
5.解决tomcat中图片上传丢失问题:参考博客文章
注:别再开发工具里面重启tomcat,在开发工具里面重启的话,会重新部署,而此时开发工具中是没有那些上传的文件的,自然重新部署会,那些原本上传的文件就不见了,上传文件路径最好设置webapps之外,可以在webapps并行的目录下,建一个upload文件,专门存储应用上传的文件。
File filepath = new File("F:\\Tomcat7\\apache-tomcat-7.0.79\\images");
// 如果保存文件的目录不存在,创建upload文件夹
if (!filepath.exists()) {
filepath.mkdirs();
}
结果演示:
01.默认浏览器打开为:
02.其他浏览器打开为:
(三)实现文件下载
项目结构:
01.下载页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>
<h1>文件上传成功</h1>
<form >
<table border="1">
<tr>
<th>图片展示</th>
<th>操作</th>
</tr>
<c:forEach items="${filenames}" var="newfilename">
<!--路径为以下形式,浏览器可以打开图片-->
<td><img alt="" src="/FileDownload/images/${newfilename}" width="140" height="170"/> </td>
<!--下载图片-->
<td><a href="${pageContext.request.contextPath}/download?filename=${newfilename}">下载</a></td>
</c:forEach>
</table>
</form>
</body>
</html>
02.FileDownloadController .java
package com.wang;
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FileDownloadController {
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(String filename,
HttpServletRequest request ) throws IOException{
//指定下载文件所在的位置
String path = request.getServletContext().getRealPath("/images");
//创建文件对象
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);
}
}
结果演示:
(四)解决中文名称文件下载
注:一般也不会使用汉字作为资源文件名,没多大意思还给自己带来麻烦!
1.download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page import="java.net.URLEncoder"%>
<!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>
2.FileDownloadController.java
package com.wang;
import java.io.File;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FileDownloadController {
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,
String filename) throws Exception{
// 指定要下载的文件所在路径
String path = request.getServletContext().getRealPath("/images");
// 创建该文件对象
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);
// 使用Sring 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[] 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");
}
}