SpringBoot文件上傳大小限制配置全指南
一、問題本質(zhì)
當(dāng)客戶端上傳文件超過服務(wù)端限制時(shí),Servlet 容器(Tomcat)直接拒絕請(qǐng)求,返回 HTTP 413 Request Entity Too Large,請(qǐng)求根本不會(huì)到達(dá)你的 Controller 代碼。
客戶端上傳 5MB 文件
↓
Tomcat 檢查:max-file-size = 1MB(默認(rèn))
↓
5MB > 1MB → 直接拒絕,返回 413
↓
你的 Controller 代碼完全不會(huì)執(zhí)行二、Spring Boot 文件上傳相關(guān)配置項(xiàng)
spring:
servlet:
multipart:
enabled: true # 是否啟用 multipart 支持
max-file-size: 10MB # 單個(gè)文件最大大小
max-request-size: 30MB # 整個(gè)請(qǐng)求體最大大小
file-size-threshold: 0B # 超過多大寫入臨時(shí)文件(0表示始終寫磁盤)
location: # 臨時(shí)文件存儲(chǔ)目錄
resolve-lazily: false # 是否延遲解析 multipart 請(qǐng)求2.1 各配置項(xiàng)詳解
| 配置項(xiàng) | 默認(rèn)值 | 含義 | 觸發(fā)時(shí)機(jī) |
|---|---|---|---|
enabled | true | 是否開啟文件上傳功能 | 應(yīng)用啟動(dòng)時(shí) |
max-file-size | 1MB | 單個(gè)上傳文件的最大大小 | Tomcat 解析請(qǐng)求體時(shí) |
max-request-size | 10MB | 整個(gè) multipart 請(qǐng)求的最大大?。ㄋ形募?表單字段之和) | Tomcat 解析請(qǐng)求體時(shí) |
file-size-threshold | 0B | 文件大小超過此值時(shí)寫入磁盤臨時(shí)文件,否則保留在內(nèi)存 | 解析文件時(shí) |
location | 系統(tǒng)臨時(shí)目錄 | 臨時(shí)文件存放路徑 | 寫入臨時(shí)文件時(shí) |
resolve-lazily | false | true 則延遲到實(shí)際使用 file 時(shí)才解析 | 請(qǐng)求進(jìn)入時(shí) |
2.2 max-file-size vs max-request-size
一個(gè) multipart 請(qǐng)求可能包含: ├── file1: 8MB(圖片) ├── file2: 5MB(文檔) ├── name: "張三"(文本字段,幾字節(jié)) └── 總請(qǐng)求體大小: ~13MB + boundary 開銷 max-file-size = 10MB → file1(8MB) 通過,如果 file1 是 12MB 則被拒 max-request-size = 30MB → 整體 13MB 通過,如果總體超過 30MB 則被拒
單文件接口:max-request-size 略大于 max-file-size 即可(額外空間給表單字段和 boundary)。
多文件接口:max-request-size 應(yīng)為 max-file-size × 文件數(shù) + 余量。
2.3 file-size-threshold 的作用
上傳文件 → Tomcat 解析
├── 文件 < file-size-threshold → 保留在 JVM 內(nèi)存中(快,但占堆內(nèi)存)
└── 文件 >= file-size-threshold → 寫入磁盤臨時(shí)文件(慢,但不占堆內(nèi)存)
| 場(chǎng)景 | 建議值 |
|---|---|
| 文件很?。^像、圖標(biāo)) | 256KB~1MB(保留內(nèi)存,減少磁盤IO) |
| 文件較大(Excel、視頻) | 0B(默認(rèn),始終寫磁盤,保護(hù)堆內(nèi)存) |
| 高并發(fā)小文件 | 適當(dāng)調(diào)大,減少磁盤寫入 |
2.4 resolve-lazily 的作用
resolve-lazily: true
- false(默認(rèn)):請(qǐng)求一進(jìn)來就解析整個(gè) multipart body
- true:延遲到 Controller 中第一次使用
MultipartFile參數(shù)時(shí)才解析
用途:配合異常處理,在解析失敗時(shí)能被全局異常處理器捕獲(默認(rèn)模式下解析在 Filter 層就完成了,異常可能無法被 @ControllerAdvice 捕獲)。
三、大小單位寫法
Spring Boot 支持以下寫法:
| 寫法 | 含義 |
|---|---|
10MB | 10 兆字節(jié) |
10485760 | 精確字節(jié)數(shù)(10×1024×1024) |
1GB | 1 吉字節(jié) |
512KB | 512 千字節(jié) |
-1 | 不限制大小 |
四、超出限制時(shí)的異常處理
4.1 默認(rèn)行為
超出 max-file-size 或 max-request-size 時(shí),Spring 拋出 MaxUploadSizeExceededException(繼承自 MultipartException)。
默認(rèn)情況下返回 413 或 500 錯(cuò)誤頁(yè),對(duì)用戶不友好。
4.2 全局異常處理器捕獲
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 文件大小超出限制.
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleMaxUploadSize(MaxUploadSizeExceededException e) {
return Map.of(
"success", false,
"errorMsg", "上傳文件過大,請(qǐng)控制在規(guī)定大小以內(nèi)"
);
}
/**
* Multipart 解析異常(文件損壞、格式錯(cuò)誤等).
*/
@ExceptionHandler(MultipartException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleMultipart(MultipartException e) {
return Map.of(
"success", false,
"errorMsg", "文件上傳失?。? + e.getMessage()
);
}
}
4.3 配合 resolve-lazily 使用
如果全局異常處理器捕獲不到 MaxUploadSizeExceededException,可以開啟延遲解析:
spring:
servlet:
multipart:
resolve-lazily: true這樣異常會(huì)在 Controller 方法執(zhí)行時(shí)拋出,能被 @ControllerAdvice 正常捕獲。
五、兩層限制策略
生產(chǎn)環(huán)境推薦「Servlet 容器兜底 + 代碼精確校驗(yàn)」雙層策略:
┌─────────────────────────────────────┐
請(qǐng)求進(jìn)入 ──→ │ Servlet 容器層(yml 配置) │
│ max-file-size: 30MB │
│ 作用:防御惡意超大請(qǐng)求,保護(hù)服務(wù)器 │
│ 超出時(shí):直接 413 拒絕 │
└─────────────────────┬───────────────┘
↓ 通過
┌─────────────────────────────────────┐
│ Controller 代碼層 │
│ if (file.getSize() > 20MB) │
│ 作用:業(yè)務(wù)級(jí)精確校驗(yàn) │
│ 超出時(shí):返回友好提示 │
└─────────────────────┬───────────────┘
↓ 通過
┌─────────────────────────────────────┐
│ Service 業(yè)務(wù)邏輯 │
└─────────────────────────────────────┘
為什么需要兩層:
| 只有 yml | 只有代碼 | 兩層配合 |
|---|---|---|
| 用戶看到 413 錯(cuò)誤頁(yè),不友好 | 惡意超大文件能打進(jìn)來,Tomcat 解析消耗內(nèi)存 | 兼顧安全和體驗(yàn) |
設(shè)值策略:
yml(兜底)> 代碼(業(yè)務(wù)限制)> 實(shí)際最大文件 示例:yml 設(shè) 30MB > 代碼限制 20MB > 實(shí)際文件最大 ~8MB
六、完整示例
6.1 application.yml
spring:
servlet:
multipart:
enabled: true
max-file-size: 30MB # Servlet 容器兜底:允許最大30MB進(jìn)來
max-request-size: 35MB # 請(qǐng)求體總大?。何募?表單字段
file-size-threshold: 0B # 始終寫臨時(shí)文件,保護(hù)堆內(nèi)存
resolve-lazily: true # 延遲解析,便于異常處理器捕獲
server:
port: 8080
tomcat:
max-swallow-size: 30MB # Tomcat 讀取請(qǐng)求體的最大大小(需與上面一致)6.2 Controller
package com.example.controller;
import java.util.Map;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/api/file")
public class FileUploadController {
/** 業(yè)務(wù)層文件大小限制:20MB. */
private static final long MAX_FILE_SIZE = 20L * 1024 * 1024;
/** 允許的文件類型. */
private static final String[] ALLOWED_EXTENSIONS = {".xlsx", ".xls", ".csv"};
@PostMapping("/upload")
public Map<String, Object> upload(
@RequestParam("file") MultipartFile file,
@RequestParam("operator") String operator) {
// 1. 空文件校驗(yàn)
if (file == null || file.isEmpty()) {
return Map.of("success", false, "errorMsg", "請(qǐng)選擇要上傳的文件");
}
// 2. 文件大小校驗(yàn)(業(yè)務(wù)級(jí),給用戶友好提示)
if (file.getSize() > MAX_FILE_SIZE) {
return Map.of("success", false, "errorMsg",
"文件大小不能超過20MB,當(dāng)前文件大?。? + formatSize(file.getSize()));
}
// 3. 文件類型校驗(yàn)
String fileName = file.getOriginalFilename();
if (!isAllowedExtension(fileName)) {
return Map.of("success", false, "errorMsg",
"不支持的文件格式,僅支持:xlsx、xls、csv");
}
// 4. 業(yè)務(wù)處理...
return Map.of("success", true, "data", Map.of(
"fileName", fileName,
"fileSize", formatSize(file.getSize()),
"operator", operator
));
}
private boolean isAllowedExtension(String fileName) {
if (fileName == null) return false;
String lower = fileName.toLowerCase();
for (String ext : ALLOWED_EXTENSIONS) {
if (lower.endsWith(ext)) return true;
}
return false;
}
private String formatSize(long bytes) {
if (bytes < 1024) return bytes + "B";
if (bytes < 1024 * 1024) return String.format("%.1fKB", bytes / 1024.0);
return String.format("%.1fMB", bytes / (1024.0 * 1024));
}
}
6.3 全局異常處理器
package com.example.config;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
/**
* 全局異常處理器.
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 處理文件超出 Servlet 容器層限制的情況.
* 當(dāng)文件超過 yml 中配置的 max-file-size 時(shí)觸發(fā).
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleMaxUploadSize(MaxUploadSizeExceededException e) {
return Map.of(
"success", false,
"errorMsg", "文件過大,服務(wù)器最大允許30MB"
);
}
/**
* 處理其他 Multipart 解析異常.
*/
@ExceptionHandler(MultipartException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleMultipartException(MultipartException e) {
return Map.of(
"success", false,
"errorMsg", "文件上傳失敗"
);
}
}
6.4 測(cè)試效果
# 正常文件(5MB)→ 通過兩層檢查,正常處理
curl -F "file=@small.xlsx" -F "operator=test" http://localhost:8080/api/file/upload
# {"success":true,"data":{"fileName":"small.xlsx","fileSize":"5.2MB","operator":"test"}}
# 中等文件(25MB)→ 通過 yml 30MB 限制,但被代碼 20MB 校驗(yàn)攔截
curl -F "file=@medium.xlsx" -F "operator=test" http://localhost:8080/api/file/upload
# {"success":false,"errorMsg":"文件大小不能超過20MB,當(dāng)前文件大?。?5.3MB"}
# 超大文件(50MB)→ 被 yml 30MB 限制攔截,觸發(fā)全局異常處理器
curl -F "file=@large.xlsx" -F "operator=test" http://localhost:8080/api/file/upload
# {"success":false,"errorMsg":"文件過大,服務(wù)器最大允許30MB"}
七、常見問題
7.1 Tomcat 的 max-swallow-size
server:
tomcat:
max-swallow-size: 30MBTomcat 有一個(gè)獨(dú)立的配置 max-swallow-size(默認(rèn) 2MB),作用是:當(dāng)請(qǐng)求被拒絕(如413)時(shí),Tomcat 是否繼續(xù)讀取剩余請(qǐng)求體。如果不配置,客戶端可能收到 connection reset 而非正常的錯(cuò)誤響應(yīng)。
建議設(shè)為和 max-request-size 一致。
7.2 Nginx 反向代理的限制
如果服務(wù)前面有 Nginx,還需要配置 Nginx 的 client_max_body_size:
server {
client_max_body_size 30m; # 必須 >= Spring Boot 的 max-request-size
}否則 Nginx 層面就返回 413 了,請(qǐng)求到不了 Spring Boot。
7.3 完整鏈路的大小限制
客戶端 → Nginx(client_max_body_size) → Tomcat(max-swallow-size)
→ Spring(max-request-size / max-file-size) → Controller(代碼校驗(yàn))
每一層都要 >= 你期望允許的最大文件大小
八、不同場(chǎng)景的推薦配置
| 場(chǎng)景 | max-file-size | max-request-size | 代碼校驗(yàn) |
|---|---|---|---|
| 頭像上傳(< 2MB) | 5MB | 5MB | 2MB |
| Excel 導(dǎo)入(< 20MB) | 30MB | 35MB | 20MB |
| 視頻上傳(< 500MB) | 600MB | 600MB | 500MB |
| 不限制 | -1 | -1 | 按需 |
原則:yml 配置比代碼校驗(yàn)寬松 30%~50%,作為安全兜底。
以上就是SpringBoot文件上傳大小限制配置全指南的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot文件上傳大小限制配置的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Idea?中控制啟動(dòng)命令的詳細(xì)過程?區(qū)分環(huán)境案例詳解
這篇文章主要介紹了Idea?中控制啟動(dòng)命令的詳細(xì)過程?區(qū)分環(huán)境案例詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08
Java 內(nèi)存模型中的happen-before關(guān)系詳解
這篇文章主要為大家介紹了Java 內(nèi)存模型中的happen-before關(guān)系示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
一文詳解Java中Integer是如何應(yīng)用享元模式的
在Java中,享元模式在Integer和String類中有顯著的應(yīng)用,下面這篇文章主要介紹了Java中Integer是如何應(yīng)用享元模式的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-10-10
mybatis的坑-integer類型為0的數(shù)據(jù)if?test失效問題
這篇文章主要介紹了mybatis的坑-integer類型為0的數(shù)據(jù)if?test失效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
Java中JavaBean對(duì)象和Map的互相轉(zhuǎn)換方法實(shí)例
為什么需要將javaBean和map進(jìn)行轉(zhuǎn)換,在很多應(yīng)用場(chǎng)景中,需要將key=value形式的數(shù)據(jù)與javaBean對(duì)象相互轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于Java中JavaBean對(duì)象和Map的互相轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下2022-11-11
spring boot中各個(gè)版本的redis配置問題詳析
這篇文章主要給大家介紹了關(guān)于spring boot中各個(gè)版本的redis配置問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
深入解析Spring Cloud內(nèi)置的Zuul過濾器
這篇文章主要給大家深入的介紹了Spring Cloud內(nèi)置的Zuul過濾器的相關(guān)資料,文中給大家介紹的很詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。2017-02-02
小議Java的源文件的聲明規(guī)則以及編程風(fēng)格
這篇文章主要介紹了小議Java的源文件的聲明規(guī)則以及編程風(fēng)格,僅給Java初學(xué)者作一個(gè)簡(jiǎn)單的示范,需要的朋友可以參考下2015-09-09

