前言
來(lái)啦老鐵!
筆者學(xué)習(xí)Spring Boot有一段時(shí)間了,附上Spring Boot系列學(xué)習(xí)文章,歡迎取閱、賜教:
- 5分鐘入手Spring Boot;
- Spring Boot數(shù)據(jù)庫(kù)交互之Spring Data JPA;
- Spring Boot數(shù)據(jù)庫(kù)交互之Mybatis;
- Spring Boot視圖技術(shù);
- Spring Boot之整合Swagger;
- Spring Boot之junit單元測(cè)試踩坑;
- 如何在Spring Boot中使用TestNG;
- Spring Boot之整合logback日志;
- Spring Boot之整合Spring Batch:批處理與任務(wù)調(diào)度;
- Spring Boot之整合Spring Security: 訪問(wèn)認(rèn)證;
- Spring Boot之整合Spring Security: 授權(quán)管理;
- Spring Boot之多數(shù)據(jù)庫(kù)源:極簡(jiǎn)方案;
- Spring Boot之使用MongoDB數(shù)據(jù)庫(kù)源;
- Spring Boot之多線程、異步:@Async;
- Spring Boot之前后端分離(一):Vue前端;
- Spring Boot之前后端分離(二):后端、前后端集成;
- Spring Boot之前后端分離(三):登錄、登出、頁(yè)面認(rèn)證;
- Spring Boot之面向切面編程:Spring AOP;
- Spring Boot之集成Redis(一):Redis初入門(mén);
- Spring Boot之集成Redis(二):集成Redis;
- Spring Boot之集成Redis(三):Spring Cache + Redis;
Redis挖了好大一個(gè)坑,肝了好幾天,Redis暫時(shí)就學(xué)到這吧,今天我們來(lái)學(xué)點(diǎn)輕松的!
最近換電腦,需要把舊電腦上的一些資料傳到新電腦,很多人是將舊電腦的資料上傳到云盤(pán),然后新電腦再?gòu)脑票P(pán)下載,這個(gè)過(guò)程本沒(méi)有問(wèn)題,我也經(jīng)常這么干,但問(wèn)題是云盤(pán)上傳文件的速度跟蝸牛爬一樣,于是有了今天這一說(shuō):
-
Spring Boot之文件上傳、下載
項(xiàng)目代碼已上傳Git Hub倉(cāng)庫(kù),歡迎取閱:
整體步驟
- 添加文件限制配置或編寫(xiě)文件限制配置類;
- 編寫(xiě)演示用文件上傳API;
- 編寫(xiě)演示用文件下載API;
- 文件上傳、下載演示;
1. 添加文件限制配置或編寫(xiě)文件限制配置類;
Spring Boot的默認(rèn)單次上傳文件的大小為10 MB,在沒(méi)有額外干預(yù)的情況下,上傳超過(guò)10 MB的文件,會(huì)有類似這樣的報(bào)錯(cuò):
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)
我們可以通過(guò)2種方式將這一限制擴(kuò)大。
1). 添加文件限制配置方式;
這個(gè)方式很簡(jiǎn)單,比如我們想將文件限制放大到10 GB,只需要在application.properties文件中添加以下類似配置即可:
#單個(gè)文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#單個(gè)請(qǐng)求,文件總大小限制
spring.servlet.multipart.max-request-size=10240MB
application.properties文件整體樣子:
server.port=8080
#單個(gè)文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#單個(gè)請(qǐng)求,文件大小限制
spring.servlet.multipart.max-request-size=10240MB
#默認(rèn)文件上傳功能,文件保存的根目錄
file.upload.dir=E:\\Resource\\spring-boot-cloud\\
#默認(rèn)文件下載功能,文件保存的根目錄
file.download.dir=E:\\Resource\\spring-boot-cloud\\
2). 編寫(xiě)文件限制配置類方式;
這種方式也加單,新建config包,在包內(nèi)創(chuàng)建一個(gè)MultipartConfig.java類(名字不限),類中寫(xiě)入以下代碼:
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. 編寫(xiě)演示用文件上傳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. 編寫(xiě)演示用文件下載API;
為了系統(tǒng)學(xué)習(xí)文件上傳與下載,我又實(shí)現(xiàn)了一個(gè)文件下載的API。
新建FileDownloadController.java類,寫(xiě)入代碼:
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). 文件上傳:
上傳前:

上傳:


上傳后:

咱們來(lái)稍微解讀一下:
(1). 由于我要快速實(shí)現(xiàn)上傳接口,用于傳文件,所以我沒(méi)有做過(guò)多的驗(yàn)證和邏輯處理,關(guān)鍵代碼只有3行:
String fileName = file.getOriginalFilename();
File dest = new File(rootPath + fileName);
file.transferTo(dest);
即API拿到傳來(lái)的文件,拿其文件名,拼出服務(wù)器的文件路徑,保存就完事了!
(2). 我們可以在application.properties自定義一個(gè)默認(rèn)的上傳文件保存根目錄,然后用@Value注解引用進(jìn)項(xiàng)目,如:
@Value(value = "${file.upload.dir}")
private String rootPath;
(3). 文件上傳還是挺快的,經(jīng)試驗(yàn),2G的文件約600秒完成上傳,平均3.4 MB/s,況且我們省去了下載的動(dòng)作,相比于上傳到云盤(pán),再下載到新電腦的方式,簡(jiǎn)直是太快了!
(4). 上傳的速度應(yīng)該受我局域網(wǎng)設(shè)備(路由器)、局域網(wǎng)帶寬等的限制,但即使這樣,速度也是比云盤(pán)那種方式快多了,而且速度十分穩(wěn)定!
2). 文件下載:
(文件下載的功能是我們自己學(xué)習(xí)用的,與本次解決換電腦文件傳輸慢的問(wèn)題無(wú)關(guān)。)
由于我們寫(xiě)的是GET API,可在瀏覽器直接訪問(wèn)下載API,如:http://192.168.0.105:8080/api/file?fileName=Postman-win64-7.32.0-Setup.exe

速度也是賊快哦!
至此,我們?cè)赟pring Boot項(xiàng)目中實(shí)現(xiàn)了文件的上傳、下載,整個(gè)過(guò)程非常輕松,可謂絲滑,讀者可自行擴(kuò)展,如批量文件上傳、下載等。
而經(jīng)過(guò)此次的學(xué)習(xí),我想我知道怎么做一個(gè)個(gè)人網(wǎng)盤(pán)了,你呢?
如果本文對(duì)您有幫助,麻煩點(diǎn)贊、關(guān)注!
謝謝!