前言
来啦老铁!
笔者学习Spring Boot有一段时间了,附上Spring Boot系列学习文章,欢迎取阅、赐教:
- 5分钟入手Spring Boot;
- Spring Boot数据库交互之Spring Data JPA;
- Spring Boot数据库交互之Mybatis;
- Spring Boot视图技术;
- Spring Boot之整合Swagger;
- Spring Boot之junit单元测试踩坑;
- 如何在Spring Boot中使用TestNG;
- Spring Boot之整合logback日志;
- Spring Boot之整合Spring Batch:批处理与任务调度;
- Spring Boot之整合Spring Security: 访问认证;
- Spring Boot之整合Spring Security: 授权管理;
- Spring Boot之多数据库源:极简方案;
- Spring Boot之使用MongoDB数据库源;
- Spring Boot之多线程、异步:@Async;
- Spring Boot之前后端分离(一):Vue前端;
- Spring Boot之前后端分离(二):后端、前后端集成;
- Spring Boot之前后端分离(三):登录、登出、页面认证;
- Spring Boot之面向切面编程:Spring AOP;
- Spring Boot之集成Redis(一):Redis初入门;
- Spring Boot之集成Redis(二):集成Redis;
- Spring Boot之集成Redis(三):Spring Cache + Redis;
Redis挖了好大一个坑,肝了好几天,Redis暂时就学到这吧,今天我们来学点轻松的!
最近换电脑,需要把旧电脑上的一些资料传到新电脑,很多人是将旧电脑的资料上传到云盘,然后新电脑再从云盘下载,这个过程本没有问题,我也经常这么干,但问题是云盘上传文件的速度跟蜗牛爬一样,于是有了今天这一说:
-
Spring Boot之文件上传、下载
项目代码已上传Git Hub仓库,欢迎取阅:
整体步骤
- 添加文件限制配置或编写文件限制配置类;
- 编写演示用文件上传API;
- 编写演示用文件下载API;
- 文件上传、下载演示;
1. 添加文件限制配置或编写文件限制配置类;
Spring Boot的默认单次上传文件的大小为10 MB,在没有额外干预的情况下,上传超过10 MB的文件,会有类似这样的报错:
org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
at org.apache.tomcat.util.http.fileupload.impl.FileItemStreamImpl$1.raiseError(FileItemStreamImpl.java:114)
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.checkLimit(LimitedInputStream.java:76)
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:135)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:98)
at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:291)
at org.apache.catalina.connector.Request.parseParts(Request.java:2869)
at org.apache.catalina.connector.Request.getParts(Request.java:2771)
at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098)
我们可以通过2种方式将这一限制扩大。
1). 添加文件限制配置方式;
这个方式很简单,比如我们想将文件限制放大到10 GB,只需要在application.properties文件中添加以下类似配置即可:
#单个文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#单个请求,文件总大小限制
spring.servlet.multipart.max-request-size=10240MB
application.properties文件整体样子:
server.port=8080
#单个文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#单个请求,文件大小限制
spring.servlet.multipart.max-request-size=10240MB
#默认文件上传功能,文件保存的根目录
file.upload.dir=E:\\Resource\\spring-boot-cloud\\
#默认文件下载功能,文件保存的根目录
file.download.dir=E:\\Resource\\spring-boot-cloud\\
2). 编写文件限制配置类方式;
这种方式也加单,新建config包,在包内创建一个MultipartConfig.java类(名字不限),类中写入以下代码:
package com.github.dylanz666.config;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;
import javax.servlet.MultipartConfigElement;
/**
* @author : dylanz
* @since : 11/02/2020
*/
@Configuration
public class MultipartConfig {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory multipartConfigFactory = new MultipartConfigFactory();
multipartConfigFactory.setMaxFileSize(DataSize.parse("10240MB"));
multipartConfigFactory.setMaxRequestSize(DataSize.parse("10240MB"));
return multipartConfigFactory.createMultipartConfig();
}
}
2种方式效果一样,任君选择!
2. 编写演示用文件上传API;
package com.github.dylanz666.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/**
* @author : dylanz
* @since : 11/02/2020
*/
@RestController
@RequestMapping("/api")
public class FileUploadController {
@Value(value = "${file.upload.dir}")
private String rootPath;
@GetMapping("/upload/ping")
public String ping() {
return "success";
}
@PostMapping("/file")
public Boolean upload(@RequestParam("file") MultipartFile file) {
try {
String fileName = file.getOriginalFilename();
assert fileName != null;
System.out.println(fileName);
File dest = new File(rootPath, fileName);
file.transferTo(dest);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
3. 编写演示用文件下载API;
为了系统学习文件上传与下载,我又实现了一个文件下载的API。
新建FileDownloadController.java类,写入代码:
package com.github.dylanz666.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Objects;
/**
* @author : dylanz
* @since : 11/08/2020
*/
@RestController
@RequestMapping("/api")
public class FileDownloadController {
@Value(value = "${file.download.dir}")
private String rootPath;
private FileInputStream fis = null;
private BufferedInputStream bis = null;
@GetMapping("/download/ping")
public String ping() {
return "success";
}
@GetMapping("/file")
public String download(@RequestParam String fileName) {
try {
File file = new File(rootPath, fileName);
HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
assert response != null;
response.setContentType("application/force-download");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
if (file.exists()) {
byte[] buffer = new byte[1024];
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
}
return "success";
} catch (Exception e) {
e.printStackTrace();
return "fail";
} finally {
try {
bis.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
4. 文件上传、下载演示;
1). 文件上传:
上传前:
上传:
上传后:
咱们来稍微解读一下:
(1). 由于我要快速实现上传接口,用于传文件,所以我没有做过多的验证和逻辑处理,关键代码只有3行:
String fileName = file.getOriginalFilename();
File dest = new File(rootPath + fileName);
file.transferTo(dest);
即API拿到传来的文件,拿其文件名,拼出服务器的文件路径,保存就完事了!
(2). 我们可以在application.properties自定义一个默认的上传文件保存根目录,然后用@Value注解引用进项目,如:
@Value(value = "${file.upload.dir}")
private String rootPath;
(3). 文件上传还是挺快的,经试验,2G的文件约600秒完成上传,平均3.4 MB/s,况且我们省去了下载的动作,相比于上传到云盘,再下载到新电脑的方式,简直是太快了!
(4). 上传的速度应该受我局域网设备(路由器)、局域网带宽等的限制,但即使这样,速度也是比云盘那种方式快多了,而且速度十分稳定!
2). 文件下载:
(文件下载的功能是我们自己学习用的,与本次解决换电脑文件传输慢的问题无关。)
由于我们写的是GET API,可在浏览器直接访问下载API,如:http://192.168.0.105:8080/api/file?fileName=Postman-win64-7.32.0-Setup.exe
速度也是贼快哦!
至此,我们在Spring Boot项目中实现了文件的上传、下载,整个过程非常轻松,可谓丝滑,读者可自行扩展,如批量文件上传、下载等。
而经过此次的学习,我想我知道怎么做一个个人网盘了,你呢?
如果本文对您有帮助,麻烦点赞、关注!
谢谢!