今天总结下Spring中的文件上传与下载,在写这篇博客以前,小编写过一篇有关文件上传下载的博文------React Native 上传图片至七牛云存储,该博文主要聊到采用React Native 框架如何将文件上传到七牛云存储上,后端部分主要集成了七牛云提供的API,但并无从底层讲到文件上传下载的基本原理,因此本篇博文尽可能弥补以前的不足,接下来,咱们一块儿开始吧!html
就Java web 而言,对于文件上传,前端浏览器提交一个文件,而后后端处理返回文件上传成功或者失败的结果;对于文件下载,不少状况就是前端单击某个按钮或者点击某个文字连接,而后浏览器就会自动将文件上传到本地中。那么这其中的原理是什么呢?小编认为,文件的上传下载本质上是经过Java 提供的流API来处理的,在Servlet中咱们可使用Http相关的HttpServletResponse
对象将文件流输出到浏览器,固然这涉及到咱们浏览器如何识别该流是一个文件仍是一个文本字符串的问题,因此文件上传下载还提到了Http请求头Mime类型的设置.前端
小编之前会想这么一个问题,我如今会使用html表单来上传一个文件,但当我使用一个框架的时候,我就不太明白其中的原理了。关于这个问题,小编认为原理都是同样的,最本质的,都是经过表单来提交文件上传请求,也就是html中的<input type="file"/>
标签,不管你框架怎么封装,底层就是一个表单。下面咱们讲下如何Spring boot 来实现文件上传下载,本示例前端部分采用简单的html表单,没有用到任何框架,简单易懂。java
在Spring 框架中,对于文件上传下载的支持是经过MultipartFile
接口来实现的,一个MultipartFile
就表示客户端传过来的一个文件,而一个MultipartFile[]
数组,则表示客户端传过来的多个文件,这在实现多文件上传很是有用,固然了,经过该接口,你能够获取客户端传过来的文件的一些基本信息,好比文件名称、文件大小等.固然你也可让Spring限制客户端传过来文件的大小和类型(好比图片文件png
仍是文本文件txt
),但这些功能的实现配置不在本文的范围内。web
Spring MVC传统的REST风格用法是经过@Controller
、@ResponseBody
和@RequestMapping
三个注解实现的,在Spring Boot 中,你只须要使用@RestController
和@RequestMapping
两个注解便可,简单示例以下:spring
/**
* 测试文件上传与下载
*
* @author hjw
*
*/
@RestController
public class FileUploadCotroller {
@RequestMapping(value = "/upload.json", method = RequestMethod.POST)
public boolean fileUpload( MultipartFile file) throws IllegalStateException, IOException {
return false;
}
}
复制代码
因为Spring框架依赖了commons-fileupload
包,所以,咱们须要在Maven的pom.xml
文件中将该jar包引进来。json
pom.xml
后端
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
复制代码
upload.html
数组
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="http://localhost:8081/upload.json" method="POST" enctype="multipart/form-data">
<input name="file" type="file"/>
<button type="submit">single submit</button>
</form>
</body>
</html>
复制代码
FileUploadCotroller.java
浏览器
@RestController
public class FileUploadCotroller {
@RequestMapping(value = "/upload.json", method = RequestMethod.POST)
public boolean fileUpload( MultipartFile file) throws IllegalStateException, IOException {
if (file.getSize() == 0) {
return false;
}
System.err.println("文件是否为空 : " + file.isEmpty());
System.err.println("文件的大小为 :" + file.getSize());
System.err.println("文件的媒体类型为 : " + file.getContentType());
System.err.println("文件的名字: " + file.getName());
System.err.println("文件的originName为: " + file.getOriginalFilename());
File newFile = new File("C:\\Users\\hjw\\Desktop\\" + file.getOriginalFilename());
file.transferTo(newFile);
return true;
}
}
复制代码
上面的html文件表单要设置表单的enctype
属性为enctype="multipart/form-data"
,而且<input/>
标签的name
属性值必须和后端接口的MultipartFile
参数名一致,也就是都是file
七牛云存储
文件下载前端很简单,咱们直接使用一个<a><a/>
标签便可。
download.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="http://localhost:8081/download.json">single download</a>
</body>
</html>
复制代码
FileUploadCotroller.java
@RequestMapping(value="download.json")
public boolean download(HttpServletResponse res) throws IOException {
File file = new File("C:\\Users\\hjw\\Desktop\\design\\code\\project-1\\myapp\\src\\images\\seats\\bg1.png");
String fileName = "bg1.png";
res.setHeader("Content-Disposition", "attachment;filename=" + fileName);
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = res.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(file));
int i = bis.read(buff);
while (i != -1) {
os.write(buff, 0, buff.length);
os.flush();
i = bis.read(buff);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("success");
return false;
}
}
复制代码
上面的文件下载采用流的形式进行传输,注意,要实现文件下载功能,咱们必须在响应头中设置Http Header
的Content-Disposition
参数,该参数会激活浏览器的下载功能,并接受咱们传输的文件。
上面提到多文件上传对应MultipartFile[]
数组,所以咱们只需改下后端的参数便可。
multiUpload.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="http://localhost:8081/multiFile.json" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple="multiple" value="请选择多个文件"/>
<button type="submit">multi submit second</button>
</form>
</body>
</html>
复制代码
FileUploadCotroller.java
@RequestMapping(value="multiFile.json",method=RequestMethod.POST)
public boolean multiFile(MultipartFile[] files) throws IllegalStateException, IOException {
if(files.length == 0) {
return false;
}
File file = null;
String path = "C:\\Users\\hjw\\Desktop\\";
for (int i = 0; i < files.length; i++) {
System.err.println("第" + i + "个文件的大小为" + files[i].getSize());
System.err.println("第" + i + "个文件是否为空" + files[i].isEmpty());
System.err.println("第" + i + "个文件的媒体类型为" + files[i].getContentType());
System.err.println("第" + i + "个文件的文件名为" + files[i].getName());
System.err.println("第" + i + "个文件的源文件名为" + files[i].getOriginalFilename());
file = new File(path + files[i].getOriginalFilename());
files[i].transferTo(file);
}
return false;
}
复制代码
注意咱们要设置html文件<input/>
标签的multiple
属性为multiple="multiple"
,该属性表示支持文件多选操做。同时,和单文件上传相同,咱们的<input/>
标签的name
属性必须和后端的MultipartFile[]
参数名相同,即files
.
这些例子很简单,属于入门级别,固然文件上传下载作的好并非这么简单的,只不过咱们平常项目并非对文件上传下载功能要求很苛刻(好比迅雷),固然,若是你想作的高级一点,你可使用Java提供的文件随机存取类RandomAccessFile
去实现断点上传和下载,断点上传下载的功能http也是有提供相应的支持的。 谢谢阅读!