針對部門 Logo 需適應瀏覽器相容與拉伸需求,本文示範如何利用 javax.imageio.ImageReader 將上傳圖片切割為左、中、右三段與保留區,並以 Blob 存入資料庫,最後透過 CSS 精靈技術無縫拼合顯示。
<form method="post" enctype="multipart/form-data">
<input type="file" name="logoFile" id="logoFile" onchange="checkFile()" />
<input type="hidden" name="suffix" id="suffix" />
</form>
JS checkFile() 驗證副檔名 (jpg/jpeg/gif/bmp/png) 並寫入 hidden 欄位,供後端判斷格式。
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(suffix);
ImageReader reader = readers.next();
InputStream in = new BufferedInputStream(new FileInputStream(logoFile));
ImageInputStream iis = ImageIO.createImageInputStream(in);
reader.setInput(iis, true);
int imgW = reader.getWidth(0);
int imgH = 80; // 固定高度
int leftW = imgW / 2;
int midW = (imgW - leftW) / 3;
int rightW = 5;
int retainW = imgW - leftW - midW - rightW;
Rectangle leftRect = new Rectangle(0, 0, leftW, imgH);
Rectangle midRect = new Rectangle(leftW, 0, midW, imgH);
Rectangle rightRect = new Rectangle(leftW + midW, 0, rightW, imgH);
Rectangle retainRect = new Rectangle(leftW + midW + rightW, 0, retainW, imgH);
ImageReadParam param = reader.getDefaultReadParam();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
param.setSourceRegion(leftRect);
BufferedImage bi = reader.read(0, param);
ImageIO.write(bi, suffix, baos);
Blob leftBlob = Hibernate.createBlob(baos.toByteArray(), session);
baos.reset(); // 重複使用,減少物件建立
// ... 依序處理 midRect, rightRect, retainRect
logo.setLeftPartImage(leftBlob);
logo.setMiddlePartImage(midBlob);
logo.setRightPartImage(rightBlob);
logo.setRetainPartImage(retainBlob);
logo.setSuffix(suffix);
departmentManager.save(department);
<style>
#leftLogo { background: url(showLogo.action?position=left) no-repeat; width: ${leftW}px; height: 80px; }
#midLogo { background: url(showLogo.action?position=middle) no-repeat; width: ${midW}px; height: 80px; }
#rightLogo { background: url(showLogo.action?position=right) repeat-x; height: 80px; }
#retainLogo { background: url(showLogo.action?position=retain) no-repeat; width: ${retainW}px; height: 80px; }
</style>
<div id="leftLogo"></div>
<div id="midLogo"></div>
<div id="rightLogo"></div>
<div id="retainLogo"></div>
@Result(name="showLogo", type="stream",
params={"contentType", "image/jpeg,image/png,image/gif",
"inputName", "imageLogo", "bufferSize", "4096"})
public String showLogo() {
String pos = request.getParameter("position");
Blob blob = switch(pos) {
case "left" -> logo.getLeftPartImage();
case "middle" -> logo.getMiddlePartImage();
case "right" -> logo.getRightPartImage();
case "retain" -> logo.getRetainPartImage();
default -> null;
};
imageLogo = blob.getBinaryStream();
return "showLogo";
}
選單載入時讀取 Blob 寬度存入 request 屬性,EL 表達式 ${leftWidth} 直接輸出至 CSS。
方案利用 ImageReader.read(param) 精準切割、ByteArrayOutputStream 記憶體流轉 Blob、Struts2 Stream Result 直輸二進位,完整解決「上傳→切割→存儲→動態寬度→精靈拼合」全鏈路需求。