SpringMVC实现文件上传和下载和Json的简单实用
目录
SpringMVC实现文件上传和下载
1、文件下载
2、文件上传
(1)文件上传操作的分析
(2)实现步骤
(3)解决文件重名覆盖问题
Json的简单使用
1、Json概述
2、Json的语法格式
3、Jackson的QuickStart
SpringMVC实现文件上传和下载
1、文件下载
使用ResponseEntity
实现下载文件的功能
步骤
- 控制器方法形参设置为session,用于获取session
- 通过session获取到servletContext,用于获取真实路径
- 创建输入流,流的源头是 要下载文件的真实路径, 流的去向是一个字节数组,可以指定字节数组的大小和流的字节数相等,省去循环的过程
- 创建responseEntity对象,请求体为填充好的字节数组,为其添加请求头和状态码
- 返回responseEntity对象即可。
响应头如何设置
先new一个HttpHeaders,它本质是一个map集合
下载时,需要为其指定headers.add("Content-Disposition", "attachment;filename=文件名"); 此处的文件名是你设置的默认名称,用户可以在下载时自行更改
不能修改,这是规定
响应状态码如何设置
HttpStatus statusCode = HttpStatus.OK;
完整示例
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中,文件的真实路径
String realPath = servletContext.getRealPath("/static/img/diamond.png");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组,大小为输入流的所有字节总数
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=diamond.png");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
2、文件上传
(1)文件上传操作的分析
1、前端页面,如何提供文件上传的入口?
form表单具备这样的功能。
在表单内容中,添加type为 file 的域:
头像:<input type="file" name="photo"/><br>
是这样的效果:
再给表单设置一个提交按钮,点击提交,文件的信息就能被上传到服务器。
可以看出,将文件的信息传递给服务器非常容易。那么文件上传的核心,其实是服务器对这段数据的处理。
注意:文件上传要求form表单的请求方式必须为post
,并且添加属性enctype="multipart/form-data"
多文件上传时,input中加一个multiple
即可,否则上传时无法选中多个文件
2、为什么要添加属性enctype="multipart/form-data"
表单中,默认是通过键值对的形式传输到服务器。
进行这样的配置之后,会
使用二进制的方式传输到服务器,才能接收到文件
3、服务器如何处理,浏览器提交的文件数据
SpringMVC有一个文件上传解析器,将上传的文件封装到
MultipartFile
对象中,通过此对象可以获取文件相关信息
4、服务器如何保存上传的文件
比如做一个头像上传的功能,就在服务器中创建一个photo目录,将每个上传的图片保存在其中。
需要考虑文件重名问题。
(2)实现步骤
1、添加依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2、配置SpringMVC的文件上传解析器
配置在SpringMVC核心配置中
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
作用:将上传的文件封装成了一个MultipartFile对象
不需要手动访问,这个bean由SpringIOC容器自动访问,自动实现封装。
Spring如何知晓这个bean?
SpringMVC
通过id获取
这个文件上传解析器,所以id必须叫做multipartResolver
3、控制器方法
@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//获取上传的文件名称
String fileName = photo.getOriginalFilename();
/*
获取服务器中photo目录的路径
*/
//获取servletContext对象
ServletContext servletContext = session.getServletContext();
//获取文件保存目录的真实路径
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
//判断photoPath所对应路径是否存在
if (!file.exists()){
//如果目录不存在,则创建文件保存目录
file.mkdir();
}
//拼接文件的最终存放路径
String finalPath = photoPath + File.separator + fileName;
/*
保存文件
*/
photo.transferTo(new File(finalPath));
return "success";
}
(3)解决文件重名覆盖问题
文件重名覆盖问题的本质
如果不做处理,同名文件会发生覆盖的现象,原因是IO流默认不开启追加写入,将原有的文件中覆盖了新内容,所以
本质并不是发生了文件覆盖,而是覆盖了文件中的内容
。
解决方法,在服务器写入数据时,保证文件名不重复
。
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题
String hzName = fileName.substring(fileName.lastIndexOf("."));
//处理后的文件名
fileName = UUID.randomUUID().toString() + hzName;
做法:
保留了文件的后缀名,用一个随机的UUID作为文件名即可
。
Json的简单使用
1、Json概述
什么是json
JSON,全称是 JavaScript Object Notation,即 JavaScript对象标记法。
它是一种
轻量级
(Light-Meight)、基于文本
的(Text-Based)、可读
的(Human-Readable)格式。名称中虽然带有JavaScript,但是指其语法规则是参考JavaScript对象的,而不是指只能用于JavaScript 语言。
json采用的是
完全独立于编程语言的文本格式来存储和表示数据
,因此可以被任何语言的交互阶段使用。而且因为非常流行,所以几乎所有编程语言都有用于解析JSON的库。
json的作用
是一种
数据交换格式
,用于前端页面与服务器后台的数据交互。之前大规模使用的是XML,但它有两个问题:可读性差、文件较大。
而json的可读性好,文件更小,所以被广泛使用。
json可以用于传递对象和数组
。
为什么要使用json
业务中,经常遇到这种情况:服务器后台向前端页面发送了一些java对象,而前端需要解析这些对象,获取其中的属性并展示。
而
浏览器只能获取字符串
,不能解析java对象。所以就需要一种规范,能实现将java对象的属性写在字符串中,传递这个字符串,前端就能获取到字符串中包含的属性值,也就相当于是获取到了java对象的信息。
json就属于一种这个规范,可以
用于将java对象转换成json字符串的形式
。
json实现前后端交互的流程
后端:java对象(或数组) 经过序列化 --> json字符串
前端:json字符串 经过解析 --> 获得java对象(或数组)的数据
2、Json的语法格式
格式
对象:键值对
数据:用逗号分隔,最后一个数据末尾不能加逗号
表示对象:{ }
表示数组:[ ]
3、Jackson的QuickStart
如何在Java中使用json
目前对于Java开源的JSON类库有很多种,常用的是
Jackson
。Spring MVC的默认json解析器便是Jackson
导入依赖
<!--Jackson包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
创建实体类对象
public class User {
private String username;
private String password;
...
}
对象序列化成json
public static void main(String[] args) throws JsonProcessingException {
User user = new User("admin", "123456");
//使用ObjectMapper来序列化和反序列化
ObjectMapper mapper = new ObjectMapper();
//执行序列化
String json = mapper.writeValueAsString(user);
System.out.println("json = " + json);
}
输出:
json = {"username":"admin","password":"123456"}
json反序列化成java对象
public static void main(String[] args) throws JsonProcessingException {
//使用ObjectMapper来序列化和反序列化
ObjectMapper mapper = new ObjectMapper();
//模拟获取到一个json
String json = "{\"username\":\"admin\",\"password\":\"123456\"}";
//执行反序列化
User user = mapper.readValue(json, User.class);
System.out.println("user = " + user);
}
输出:
user = User{username='admin', password='123456'}