Spring MVC 使用介绍(十四)文件上传下载
一、概述
文件上传时,http请求头Content-Type须为multipart/form-data,有两种实现方式:
1、基于FormData对象,该方式简单灵活
2、基于<form>表单元素,method设为POST,enctype设置为multipart/form-data,在form表单上提交
web容器收到该请求时,须根据请求头将字节流解析为文件对象,spring mvc 提供了MultipartResolver、MultipartFile两个接口用于支持文件上传功能
二、MultipartResolver & MultipartFile
1、MultipartResolver接口提供了文件解析功能,其定义如下:
public interface MultipartResolver {
boolean isMultipart(HttpServletRequest request);
MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
void cleanupMultipart(MultipartHttpServletRequest request);
}
Spring MVC使用Apache Commons fileupload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver
2、MultipartFile接口代表上传的文件,提供了文件操作的相关功能,其定义如下:
public interface MultipartFile {
String getName();
String getOriginalFilename(); // 原文件名
String getContentType();
boolean isEmpty();
long getSize();
byte[] getBytes() throws IOException;
InputStream getInputStream() throws IOException; // 获取文件流
void transferTo(File dest) throws IOException, IllegalStateException; // 保存文件
}
三、使用示例
1、添加pom依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2、spring-mvc.xml中配置MultipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件大小限制,单位为字节-10Mb -->
<property name="maxUploadSize">
<value>10485760</value>
</property>
<!-- 请求的编码格式 -->
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
</bean>
3、controller
@Controller
public class FileController {
/**
* 文件存储目录
*/
private static final String uploadFolder = "d:/upload-file/"; /**
* 上传
*/
@ResponseBody
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public Map<String, String> fileUpload(@RequestParam("file") MultipartFile file, @RequestParam("fileType") String fileType) throws Exception { // 创建文件目录
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
String dateStr = sdf.format(new Date());
String dirPath = uploadFolder + dateStr;
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
} // 保存文件
String fileName = UUID.randomUUID() + this.getFileNameSuffix(file.getOriginalFilename());
File savedFile = new File(dir + "/" + fileName);
file.transferTo(savedFile); Map<String, String> result = new HashMap<String, String>();
result.put("fileName", file.getOriginalFilename());
result.put("fileType", fileType);
result.put("filePath", dateStr + "/" + fileName); return result;
} /**
* 下载
*/
@RequestMapping("/download")
public void downloadFile(@RequestParam(value = "fileName", required = false) String fileName, @RequestParam("filePath") String filePath, HttpServletResponse response) throws Exception {
File file = new File(uploadFolder + filePath);
if (!file.exists()) {
return;
} // 读取字节流到缓存
InputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[in.available()];
in.read(buffer);
in.close(); // 设置ContentType
String suff = this.getFileNameSuffix(file.getName());
if (suff != null) {
suff = suff.toLowerCase();
}
switch (suff) {
case ".jpg":
case ".jpeg":
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
break;
case ".png":
response.setContentType(MediaType.IMAGE_PNG_VALUE);
break;
case ".gif":
response.setContentType(MediaType.IMAGE_GIF_VALUE);
break;
default:
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
break;
} // 输出
response.addHeader("Content-Disposition", "attachment;filename=\"" + (StringUtils.isEmpty(fileName) ? file.getName() : fileName));
response.addHeader("Content-Length", "" + file.length());
response.setContentType("application/x-msdownload");
OutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(buffer);
out.flush();
} /**
* 获取文件名后缀*/
private String getFileNameSuffix(String fileName) { if (StringUtils.isEmpty(fileName)) {
return null;
} String suffix;
int index = fileName.lastIndexOf(".");
if (index == -1) {
suffix = null;
}
else {
suffix = fileName.substring(index);
} return suffix;
}
}
4、前端页面(test.html)
<!DOCTYPE html>
<html>
<head>
<title>test page</title>
</head>
<body>
<div>
<input id="upload" type="file" onchange="uploadFile(event)" />
</div>
<div>
<input id="download" type="button" onclick="downloadFile()" value="下载" />
</div>
</body>
<script>
var context = '/test' function uploadFile(event) {
// 文件类型过滤
var file = event.currentTarget.files[0];
var fileName = file.name;
if (/\.(jpg|jpeg|png|gif)$/i.test(fileName) == false) {
alert('提示', '不支持的图片类型,头像只支持.jpg,.jpeg,.png,.gif');
return;
} var formData = new FormData();
formData.append('fileType', 'portrait');
formData.append('file', event.currentTarget.files[0]); // 发送请求
var xhr = new XMLHttpRequest();
xhr.open('POST', context + '/upload', true);
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
document.getElementById('download').fileData = JSON.parse(xhr.responseText);
alert("上传成功");
}
}
xhr.send(formData); // 重置文件上传控件,使得重复选择同一个文件时,onchange依旧触发
event.target.value = null;
} function downloadFile() {
var fileData = document.getElementById('download').fileData;
location.href = context + '/download?filePath=' + decodeURIComponent(fileData.filePath) + '&fileName=' + decodeURIComponent(fileData.fileName);
}
</script>
</html>
访问http://file-test/test.html,可测试文件的上传下载功能
补充:示例使用@ResponseBody输出json数据,因此还需添加相关配置,详细可参考Spring MVC 使用介绍(五)—— 注解式控制器(一):基本介绍
另外,文件下载除了示例中文件流方式,还可以基于spring对静态文件的支持功能,详细可参考Spring MVC 使用介绍(十一)—— 跨域与静态资源访问
参考:
Spring MVC 使用介绍(十四)文件上传下载的更多相关文章
- JavaWeb 后端 <十四> 文件上传下载
1.文件上传与下载 案例: 注册表单/保存商品等相关模块! --à 注册选择头像 / 商品图片 (数据库:存储图片路径 / 图片保存到服务器中指定的目录) 1.1 文件上传 文件上传,要点: 前台: ...
- 使用Typescript重构axios(二十五)——文件上传下载进度监控
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- Spring MVC使用commons fileupload实现文件上传功能
通过Maven建立Spring MVC项目,引入了Spring相关jar依赖. 1.为了使用commons fileupload组件,需要在pom.xml中添加依赖: <properties&g ...
- SpringMVC 文件上传下载
目录 文件上传 MultipartFile对象 文件下载 上传下载示例 pom.xml增加 创建uploadForm.jsp 创建uploadForm2.jsp 创建userInfo.jsp spri ...
- Spring Boot2(十四):单文件上传/下载,文件批量上传
文件上传和下载在项目中经常用到,这里主要学习SpringBoot完成单个文件上传/下载,批量文件上传的场景应用.结合mysql数据库.jpa数据层操作.thymeleaf页面模板. 一.准备 添加ma ...
- salesforce 零基础学习(四十二)简单文件上传下载
项目中,常常需要用到文件的上传和下载,上传和下载功能实际上是对Document对象进行insert和查询操作.本篇演示简单的文件上传和下载,理论上文件上传后应该将ID作为操作表的字段存储,这里只演示文 ...
- MVC&WebForm对照学习:文件上传(以图片为例)
原文 http://www.tuicool.com/articles/myM7fe 主题 HTMLMVC模式Asp.net 博客园::首页:: :: :: ::管理 5 Posts :: 0 ...
- SpringMVC文件上传下载(单文件、多文件)
前言 大家好,我是bigsai,今天我们学习Springmvc的文件上传下载. 文件上传和下载是互联网web应用非常重要的组成部分,它是信息交互传输的重要渠道之一.你可能经常在网页上传下载文件,你可能 ...
- SpringBoot入门一:基础知识(环境搭建、注解说明、创建对象方法、注入方式、集成jsp/Thymeleaf、logback日志、全局热部署、文件上传/下载、拦截器、自动配置原理等)
SpringBoot设计目的是用来简化Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,SpringBoot致力于在蓬勃发 ...
- SpringMVC文件上传下载
在Spring MVC的基础框架搭建起来后,我们测试了spring mvc中的返回值类型,如果你还没有搭建好springmvc的架构请参考博文->http://www.cnblogs.com/q ...
随机推荐
- JAVA WEB快速入门之环境搭建
前言 我是一直致力于:.NET技术栈.WEB前端.架构设计相关的开发与管理工作,但因国内大环境影响及公司技术方向发生转变(由.NET全部转为JAVA),需要熟练掌握JAVA WEB相关的知识,故我也得 ...
- SpringBoot+Dubbo+Zookeeper整合搭建简单的分布式应用
为什么要使用分布式系统? 容错 减少延迟/提高性能 可用性 负载均衡 总而言之,其实目的只有一个,”用户体验“. 什么是分布式系统? 分布式系统是由使用分发中间件连接的自治计算机组成的网络.它们有助于 ...
- C#学习笔记之值类型与引用类型
[TOC] C#学习笔记之值类型与引用类型 1.值类型与引用类型 1.1 深层区别 值类型与引用类型有不同的内存分布,这导致了不同的内存管理机制: 值类型由OS负责内存管理 引用类型由垃圾回收器(GC ...
- IntelliJ IDEA下如何设置JSP模板
今天在学习Spring MVC知识时,发现自己所用的IntelliJ IDEA中自动生成的JSP文件不支持EL表达式的使用,所以就想导入新的JSP模板,方便以后使用.根据旧模板的提示,如下图 找到Se ...
- PHP接口APP接口
使用PHP来生成APP接口数据是非常简单的,如果你还不了解PHP没有关系,只需要看过PHP的基本语法,再看本示例就可以了. APP接口一般都是json格式(当然也有少数xml格式)遵循restful规 ...
- http header Content-Type之常用三种
Content-Type 用于指示资源的MIME类型 在响应头中,告诉客户端实际返回内容的类型 在请求头中,告诉服务器实际发送的数据类型 句法: Content-Type: text/html; ch ...
- 硬杠后端(后端坑系列)——Django前期工作
Django是一个开放源代码的Web应用框架,由Python写成,采用了MVC的框架模式. MVC MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件 ...
- vue px 转rem
来自:https://www.cnblogs.com/wangqiao170/p/8652505.html 侵 删 每一个认真生活的人,都值得被认真对待 vue px转换为rem 前端开发中还原设 ...
- CODING 如何使用 CODING 研发管理系统来敏捷开发
之前我们分享过<CODING 如何使用 CODING 开发 CODING>的文章,时过境迁,现在 CODING 研发管理系统已经上线了如持续集成.缺陷管理.测试管理等 DevOps 中的重 ...
- arcgis api 3.x for js 入门开发系列二十一气泡窗口信息动态配置模板
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...