目錄
一、引言
二、Spring Boot 文件上傳基礎
(一)依賴引入
(二)配置文件設置
(三)文件上傳接口編寫
(一)文件類型限制
(二)文件大小驗證
(三)防止文件覆蓋
四、Spring Boot 文件下載實現
(一)簡單文件下載接口編寫
(二)文件下載的異常處理
(三)支持斷點續傳
五、實戰案例演示
六、總結與展望
一、引言
在當今的 Web 應用開發中,文件上傳與下載功能是極為常見且重要的需求。無論是用戶上傳頭像、分享文檔,還是系統生成報告供用戶下載,都離不開這一功能模塊。Spring Boot 作為一款流行的 Java 開發框架,為我們提供了簡潔高效的方式來實現文件上傳與下載。本文將詳細介紹如何基于 Spring Boot 框架輕松搭建并實現這一功能,讓你快速掌握其核心要點與實踐技巧。
二、Spring Boot 文件上傳基礎
(一)依賴引入
在 Spring Boot 項目中,首先需要引入相關依賴。對于文件上傳功能,除了基礎的spring-boot-starter-web
依賴外,還需要添加處理文件上傳的commons-fileupload
依賴。在pom.xml
文件中添加如下依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version>
</dependency>
spring-boot-starter-web
提供了構建 Web 應用的基礎功能,而commons-fileupload
則專門用于處理文件上傳操作。
(二)配置文件設置
在application.properties
配置文件中設置與文件上傳相關的參數。例如:
?
# 設置單個文件上傳的最大大小為 10MB
spring.servlet.multipart.max-file-size=10MB
# 設置一次請求中上傳文件的總大小為 20MB
spring.servlet.multipart.max-request-size=20MB
# 設置上傳文件的臨時目錄
spring.servlet.multipart.location=/tmp/uploads?
這里分別設置了單個文件大小限制、總請求文件大小限制以及上傳文件的臨時存儲目錄。這些配置可以根據實際項目需求進行調整。
(三)文件上傳接口編寫
編寫一個簡單的文件上傳接口,接收前端傳來的文件數據。創建一個FileUploadController
類:
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;@RestController
public class FileUploadController {@PostMapping("/upload")public String uploadFile(@RequestParam("file") MultipartFile file) {if (file.isEmpty()) {return "上傳文件為空,請選擇文件后再次上傳。";}try {// 獲取文件名String fileName = file.getOriginalFilename();// 獲取文件存儲路徑,這里假設存儲在項目根目錄下的 uploads 文件夾中String filePath = System.getProperty("user.dir") + "/uploads/" + fileName;// 將文件保存到指定路徑file.transferTo(new File(filePath));return "文件上傳成功,文件路徑:" + filePath;} catch (IOException e) {e.printStackTrace();return "文件上傳失敗:" + e.getMessage();}}
}
在上述代碼中,@RestController
表示這是一個處理 RESTful 風格請求的控制器類。@PostMapping("/upload")
注解指定了該方法處理POST
請求到/upload
路徑的邏輯。@RequestParam("file") MultipartFile file
用于接收前端傳來的名為file
的文件數據。通過file.isEmpty()
判斷文件是否為空,如果不為空,則獲取文件的原始名稱getOriginalFilename()
,構建文件存儲路徑,最后使用transferTo()
方法將文件保存到指定路徑。如果保存過程中出現IOException
異常,則打印異常信息并返回錯誤提示。
(一)文件類型限制
可以通過白名單的方式對上傳文件的類型進行限制。例如,只允許上傳圖片文件(如.jpg
、.png
、.gif
):
private static final String[] ALLOWED_FILE_TYPES = { "image/jpeg", "image/png", "image/gif" };@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {if (file.isEmpty()) {return "上傳文件為空,請選擇文件后再次上傳。";}// 檢查文件類型是否在允許列表中if (!Arrays.asList(ALLOWED_FILE_TYPES).contains(file.getContentType())) {return "不允許上傳該類型的文件,請上傳圖片文件(jpg、png、gif)。";}try {// 后續文件保存邏輯...} catch (IOException e) {e.printStackTrace();return "文件上傳失敗:" + e.getMessage();}
}
上述代碼中,定義了一個允許的文件類型數組ALLOWED_FILE_TYPES
,然后在上傳文件前檢查文件的ContentType
是否在允許列表中,如果不在,則返回錯誤提示。
(二)文件大小驗證
除了配置文件中的全局限制,在代碼層面也可以再次驗證單個文件大小:
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {if (file.isEmpty()) {return "上傳文件為空,請選擇文件后再次上傳。";}// 檢查文件大小是否超過 5MBif (file.getSize() > 5 * 1024 * 1024) {return "上傳文件過大,單個文件大小不能超過 5MB。";}// 后續文件類型檢查及保存邏輯...
}
這里通過file.getSize()
獲取文件大小,并與設定的限制(5MB)進行比較,如果超過則返回錯誤提示。
(三)防止文件覆蓋
采用時間戳生成唯一文件名來防止文件覆蓋:
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {if (file.isEmpty()) {return "上傳文件為空,請選擇文件后再次上傳。";}try {// 獲取文件名String originalFileName = file.getOriginalFilename();// 獲取文件后綴名String fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));// 生成唯一文件名,使用當前時間戳String uniqueFileName = System.currentTimeMillis() + fileExtension;// 獲取文件存儲路徑,這里假設存儲在項目根目錄下的 uploads 文件夾中String filePath = System.getProperty("user.dir") + "/uploads/" + uniqueFileName;// 將文件保存到指定路徑file.transferTo(new File(filePath));return "文件上傳成功,文件路徑:" + filePath;} catch (IOException e) {e.printStackTrace();return "文件上傳失敗:" + e.getMessage();}
}
通過獲取原始文件名的后綴名,結合當前時間戳生成一個唯一的文件名,確保每次上傳的文件都有獨立的標識,避免覆蓋同名文件。
四、Spring Boot 文件下載實現
(一)簡單文件下載接口編寫
創建一個文件下載接口,如下:
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.io.File;@RestController
public class FileDownloadController {@GetMapping("/download")public ResponseEntity<FileSystemResource> downloadFile(@RequestParam("fileName") String fileName) {// 獲取文件路徑,這里假設文件存儲在項目根目錄下的 uploads 文件夾中String filePath = System.getProperty("user.dir") + "/uploads/" + fileName;File file = new File(filePath);if (file.exists()) {// 設置響應頭信息,包括文件名和文件類型HttpHeaders headers = new HttpHeaders();headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);// 返回文件資源return ResponseEntity.ok().headers(headers).body(new FileSystemResource(file));} else {return ResponseEntity.notFound().build();}}
}
在這個代碼中,@GetMapping("/download")
表示處理GET
請求到/download
路徑的邏輯。根據前端傳入的文件名參數fileName
,構建文件路徑并檢查文件是否存在。如果存在,則設置響應頭信息,包括Content-Disposition
用于指定文件名和下載方式(attachment
表示下載),Content-Type
設置為APPLICATION_OCTET_STREAM_VALUE
表示通用的二進制流文件類型。最后通過ResponseEntity
返回文件資源,若文件不存在則返回404 Not Found
狀態。
(二)文件下載的異常處理
在上述代碼中,如果文件不存在則返回404
狀態。還可以進一步處理其他可能的異常,例如文件讀取錯誤:
@GetMapping("/download")
public ResponseEntity<FileSystemResource> downloadFile(@RequestParam("fileName") String fileName) {String filePath = System.getProperty("user.dir") + "/uploads/" + fileName;File file;try {file = new File(filePath);if (file.exists()) {// 設置響應頭信息...return ResponseEntity.ok().headers(headers).body(new FileSystemResource(file));} else {return ResponseEntity.notFound().build();}} catch (Exception e) {e.printStackTrace();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();}
}
這里捕獲了可能出現的異常,并在異常發生時返回500 Internal Server Error
狀態碼,表示服務器內部錯誤。
(三)支持斷點續傳
對于大文件下載實現斷點續傳功能:
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile(@RequestParam("fileName") String fileName,@RequestHeader(value = "Range", required = false) String rangeHeader) {String filePath = System.getProperty("user.dir") + "/uploads/" + fileName;File file = new File(filePath);if (file.exists()) {try {// 獲取文件長度long fileLength = file.length();// 處理 Range 請求頭HttpHeaders headers = new HttpHeaders();if (rangeHeader!= null && rangeHeader.startsWith("bytes=")) {long startRange = Long.parseLong(rangeHeader.substring("bytes=".length()).split("-")[0]);long endRange = fileLength - 1;if (rangeHeader.contains("-")) {endRange = Long.parseLong(rangeHeader.substring("bytes=".length()).split("-")[1]);}// 設置響應頭的 Content-Range 字段headers.add(HttpHeaders.CONTENT_RANGE, "bytes " + startRange + "-" + endRange + "/" + fileLength);headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(endRange - startRange + 1));headers.add(HttpHeaders.ACCEPT_RANGES, "bytes");// 設置響應狀態碼為 206 Partial Contentreturn ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).headers(headers).body(new FileSystemResource(file).createRelative(startRange, endRange));} else {headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);return ResponseEntity.ok().headers(headers).body(new FileSystemResource(file));}} catch (Exception e) {e.printStackTrace();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();}} else {return ResponseEntity.notFound().build();}
}
在上述代碼中,首先獲取文件的總長度fileLength
。然后檢查請求頭中的Range
信息,如果存在Range
請求,則解析出起始和結束位置startRange
和endRange
,設置響應頭的Content-Range
、Content-Length
和ACCEPT_RANGES
字段,并返回206 Partial Content
狀態碼,表示部分內容響應,同時通過createRelative()
方法讀取文件指定范圍的數據返回給客戶端。如果沒有Range
請求,則按照普通下載方式設置響應頭并返回整個文件。
五、實戰案例演示
通過一個完整的 Spring Boot 項目實例,演示文件上傳與下載功能的實際應用。包括前端頁面的設計與交互(使用 HTML、JavaScript 等前端技術實現簡單的文件上傳和下載按鈕及相關提示信息),以及后端 Spring Boot 代碼的具體實現細節。展示如何將文件上傳與業務邏輯相結合,例如在用戶注冊時上傳頭像,并在用戶個人資料頁面實現頭像的下載顯示;或者在一個文檔管理系統中,實現文件的上傳、分類存儲以及用戶按需下載等功能場景。
六、總結與展望
總結本文所介紹的 Spring Boot 文件上傳與下載功能的實現步驟、關鍵要點以及注意事項。強調在實際開發過程中,安全性與穩定性是至關重要的因素,需要開發者充分考慮各種邊界情況并進行合理的處理。同時,展望未來可能的擴展方向,如與云存儲服務集成,實現更強大、靈活的文件管理功能,以滿足日益增長的業務需求。