在這篇文章中,我們將介紹如何使用Spring Boot創建一個REST API來提供服務器上的靜態圖片資源。該API包括路徑安全檢查、文件存在性驗證以及緩存控制等功能,并且代碼包含詳細的注釋以幫助理解。
Maven依賴
首先,在您的pom.xml
文件中添加以下依賴項:
<dependencies><!-- Spring Boot Starter Web for building web applications --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok to reduce boilerplate code --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><!-- For logging --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency>
</dependencies>
確保您已經正確配置了Maven項目的其他部分,如<parent>
標簽和版本管理等。
Java代碼
接下來是核心Java代碼,位于package pub.qingyun.web;
包下:
package pub.qingyun.web;import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;@RestController
@CrossOrigin
@Slf4j
public class ImageController {// 圖片根目錄private static final Path IMAGE_ROOT = Paths.get("F:", "Temp").toAbsolutePath().normalize();/*** 獲取圖片資源并返回給客戶端** @param imagePath 圖片文件的相對路徑參數* @return ResponseEntity<UrlResource> 包含圖片資源的響應實體,包含適當的HTTP狀態碼和響應頭*/@GetMapping("/showImage")public ResponseEntity<UrlResource> getImage(@RequestParam String imagePath) {long start = System.currentTimeMillis();// 參數校驗:檢查圖片路徑是否為空if (imagePath == null || imagePath.trim().isEmpty()) {log.warn("Missing imagePath parameter");return ResponseEntity.badRequest().build();}// 路徑安全檢查:防止路徑遍歷攻擊// 過濾非法字符,防止路徑穿越if (imagePath.contains("..") || imagePath.contains("\\") || imagePath.startsWith("/")) {log.warn("Forbidden path access attempt: [PATH_REDACTED]");return ResponseEntity.status(403).build();}Path resolvedPath = IMAGE_ROOT.resolve(imagePath).normalize();if (!resolvedPath.startsWith(IMAGE_ROOT)) {log.warn("Forbidden path access attempt: [PATH_REDACTED]");return ResponseEntity.status(403).build();}// 文件存在性檢查:驗證文件是否存在且為常規文件if (!Files.exists(resolvedPath) || !Files.isRegularFile(resolvedPath)) {log.info("Image not found: [PATH_REDACTED]");return ResponseEntity.notFound().build();}// 緩存文件長度,避免重復調用long fileLength = resolvedPath.toFile().length();// 創建資源對象UrlResource resource;try {resource = new UrlResource(resolvedPath.toUri());} catch (MalformedURLException e) {log.error("Failed to create resource for: [PATH_REDACTED], Malformed URL", e);return ResponseEntity.status(500).build();} catch (Exception e) {log.error("Failed to create resource for: [PATH_REDACTED]", e);return ResponseEntity.status(500).build();}// 設置響應頭信息HttpHeaders headers = new HttpHeaders();headers.setCacheControl("public, max-age=86400"); // 緩存 1 天headers.setExpires(System.currentTimeMillis() + 86400_000L); // 過期時間headers.setContentDispositionFormData("inline", resource.getFilename());log.info("getImage [PATH_REDACTED] ({} bytes) cost: {}ms", fileLength, (System.currentTimeMillis() - start));// 構建并返回成功響應return ResponseEntity.ok().headers(headers).contentType(MediaType.IMAGE_JPEG).contentLength(fileLength).body(resource);}
}
這個代碼段展示了一個簡單的Spring Boot REST控制器,用于從指定路徑加載圖片并將其作為資源返回給客戶端。它包括必要的安全措施來防止潛在的路徑遍歷攻擊,并設置了緩存控制頭以提高性能。希望這段代碼能為您提供構建自己的圖片服務的幫助!