Class ImageResponseBuilder
java.lang.Object
io.leandev.appfuse.file.ImageResponseBuilder
圖片下載 Response 建構器(支援伺服端縮圖 + 條件式下載)
專責「經轉換(縮圖 / 格式轉換)」的圖片回應,與 FileResponseBuilder(原樣串流 +
Range)分工。核心價值是把 ETag 做對且省:
- 變體 ETag:ETag =
"{fileId}-w{width}-h{height}-{format}-t{transformVersion}", 把尺寸與格式納入驗證器 → 不同尺寸各自快取、不會互相拿到錯圖(by construction)。 - pre-decode 304:在解碼之前就以 ETag 比對
If-None-Match,命中直接回 304, 完全跳過昂貴的 decode → scale → encode。 - buffered 回應:縮圖輸出大小需編碼後才知,故走記憶體 buffered(正確 Content-Length)。
本 builder 不自行解析 Range header(不像
FileResponseBuilder對串流做 byte-skip); 但因回應體為記憶體ByteArrayResource,Spring 的ResourceHttpMessageConverter會自動就已編碼的緩衝內容提供 range(回 206)——這是連貫的, 因為整張縮圖在回應時已完整編碼於記憶體。大檔仍建議用FileResponseBuilder:它串流 原始 bytes(低記憶體),而 resize 會把整個輸出載入記憶體。
無縮放需求(未呼叫 resize(Integer, Integer) 或寬高皆 null)時,自動委派 FileResponseBuilder 服務原圖
(原圖 ETag = fileId、支援 Range)。
使用範例
@GetMapping("/{id}/image")
public ResponseEntity<Resource> getImage(
@PathVariable String id,
@RequestParam(required = false) Integer width,
@RequestParam(required = false) Integer height,
@RequestHeader(value = "If-None-Match", required = false) String ifNoneMatch) {
Product product = productService.findById(id); // 權限檢查
String partition = TenantContext.getCurrentTenantId();
return ImageResponseBuilder.from(fileStorage, partition, product.getImageFileId())
.resize(width, height)
.ifNoneMatch(ifNoneMatch)
.build();
}
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionorg.springframework.http.ResponseEntity<org.springframework.core.io.Resource> build()建構 ResponseEntitycacheControl(org.springframework.http.CacheControl cacheControl) 覆寫 Cache-Control 策略(預設CacheControl.noCache)設定下載時的檔名(未設定使用原始檔名)強制下載(Content-Disposition: attachment)而非 inline 顯示設定輸出格式(如 "png"、"jpeg")static ImageResponseBuilderfrom(FileStorage fileStorage, String partition, String fileId) 建立 ImageResponseBuilderifNoneMatch(String ifNoneMatch) 設定請求的If-None-Matchheader(啟用條件式下載)宣告內容不可變,套用長效快取(見FileResponseBuilder.immutable())設定縮圖目標尺寸(等比縮小,只縮不放)
-
Method Details
-
from
建立 ImageResponseBuilder- Parameters:
fileStorage- FileStorage 實例partition- 儲存分區鍵fileId- 檔案 ID- Returns:
- ImageResponseBuilder 實例
-
resize
設定縮圖目標尺寸(等比縮小,只縮不放)
寬高皆可為 null(表示該維度不限制);皆為 null 時視為不縮放、退回原圖服務。 圖片一律保持長寬比、且僅在超過目標範圍時才縮小(見
ImageScaler.shrink(BufferedImage, Integer, Integer))。- Parameters:
width- 最大寬度(null 表不限制)height- 最大高度(null 表不限制)- Returns:
- this
-
format
設定輸出格式(如 "png"、"jpeg")
未設定時依原檔 content-type 的 subtype 推導(
image/jpeg→jpeg), 即預設不做跨格式轉換、保留原格式。- Parameters:
format- ImageIO 支援的格式字串- Returns:
- this
-
filename
設定下載時的檔名(未設定使用原始檔名)- Parameters:
filename- 顯示檔名- Returns:
- this
-
forceDownload
強制下載(Content-Disposition: attachment)而非 inline 顯示- Returns:
- this
-
ifNoneMatch
設定請求的
If-None-Matchheader(啟用條件式下載)命中時在解碼前直接回 304,跳過 decode/scale/encode。
- Parameters:
ifNoneMatch- 請求的 If-None-Match header 值,可為 null- Returns:
- this
-
immutable
宣告內容不可變,套用長效快取(見
FileResponseBuilder.immutable())縮圖是原檔(write-once)的決定性衍生,同一 (fileId, 尺寸, 格式) 的輸出永不改變, 故變體亦可安全長效快取。
- Returns:
- this
-
cacheControl
覆寫 Cache-Control 策略(預設CacheControl.noCache)- Parameters:
cacheControl- Cache-Control 策略- Returns:
- this
-
build
public org.springframework.http.ResponseEntity<org.springframework.core.io.Resource> build()建構 ResponseEntity
- 檔案不存在 → 404 Not Found
- 無縮放需求(寬高皆 null)→ 委派
FileResponseBuilder服務原圖 If-None-Match與變體 ETag 相符 → 304(解碼前短路)- 否則 → 200 OK(縮圖後的 buffered 回應)
- 來源非可解碼影像 → 退回原圖服務
- Returns:
- ResponseEntity
-