SpringBoot实现文件的上传和下载
程序员文章站
2022-06-02 14:10:41
...
文件上传和下载
一、 前端file.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传</title>
</head>
<body>
<form action="/fileUpload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value=”上传文件”>
</form>
<div>
<a href="/download">点击下载</a>
</div>
</body>
</html>
multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,且不会对字符编码。
注意:
(1)在SpringMVC中,处理文件上传需要导入依赖包commons-io
包:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
使用依赖包commons-io
的情形:
public String fileUpload(@RequestParam("file") CommonsMultipartFile
file)
(2)SpringBoot 中处理文件上传使用默认的StandardServletMultipartResolver
,相关的自动配置在MultipartAutoConfiguration
之中。我们可以使用spring.servlet.multipart
进行配置,当然也可以使用commons-io
包,不过需要将默认的方法排除掉:
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
(3)我们这里直接采用的是MultipartFile接口方法
CommonsMultipartFile 的常用方法:
String getOriginalFilename()
:获取上传文件的原名,如test.html
InputStream getInputStream()
:获取文件流
void transferTo(File dest)
:将上传文件保存到一个目录文件中
二、文件上传与下载:
- 文件上传时需要定义上传文件的地址以及文件名,从file中获取字节流,输出到指定的文件路径中。
- 文件下载时,获取下载文件的完整路径,推荐使用Buffer缓冲流的方式下载文件。
@RestController
public class TestController {
@PostMapping("/fileUpload")
public String fileUpload(HttpServletRequest req, HttpServletResponse resp,@RequestParam("file") MultipartFile file) {
if(file.isEmpty()){
return "未选择上传文件";
}
String originalFilename = file.getOriginalFilename();
String path = "G:/glp/"+originalFilename;
File dest = new File(path);
if(!dest.getParentFile().exists()){
dest.getParentFile().mkdir();
}
try{
file.transferTo(dest);
return "上传成功";
}catch (IOException e){
e.printStackTrace();
}
return "上传失败";
}
@GetMapping("/download")
public String fileDownLoad(HttpServletRequest req,HttpServletResponse resp){
File file = new File("G:/glp/高立鹏-19829497840-Java研发工程师.pdf");
if(!file.exists()){
return "下载文件不存在";
}
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));){
byte[] buff = new byte[1024];
OutputStream outputStream = resp.getOutputStream();
int len =0;
while ((len=bis.read(buff))!=-1){
outputStream.write(buff,0,len);
outputStream.flush();
}
}catch (IOException e){
e.printStackTrace();
return "下载失败";
}
return "下载成功";
}
}
注意:
这里采用了transferTo来上传文件。
三、BufferedInputStream
BufferedInputStream是一个带有缓冲区的输入流,通常使用它可以提高我们的读取效率,现在我们看下BufferedInputStream的实现原理:
- BufferedInputStream内部有一个缓冲区,默认大小为8M,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源(譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容部分或全部返回给用户.由于从缓冲区里读取数据远比直接从物理数据源(譬如文件)读取速度快,所以BufferedInputStream的效率很高!
- 不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!这就是inputstream与bufferedinputstream的区别.
- BufferedInputStream与BufferedOutputStream分别是FilterInputStream类和FilterOutputStream类的子类,实现了装饰设计模式。