項目需將存儲於 Oracle BLOB 字段的圖片經 JSON 接口返回給前端。JSON 無法直接承載二進制,常規做法是返回圖片 URL 由前端二次請求,但受限於架構必須內嵌圖片數據。Base64 編碼雖通用,但體積膨脹 33%,且作者實測解碼後圖片損壞;最終採用 ISO-8859-1 編碼 + GZIP 壓縮 方案成功落地。
private byte[] loadImage(File file) throws IOException {
try (FileInputStream fin = new FileInputStream(file);
ByteArrayOutputStream bout = new ByteArrayOutputStream((int)file.length())) {
byte[] buffer = new byte[1024];
int len;
while ((len = fin.read(buffer)) != -1) {
bout.write(buffer, 0, len);
}
return bout.toByteArray();
}
}
private String bytesToString(byte[] data) throws UnsupportedEncodingException {
return new String(data, "ISO-8859-1"); // 單字節編碼,無損映射 0-255
}
private String compress(String data) throws IOException {
try (ByteArrayOutputStream bout = new ByteArrayOutputStream();
GZIPOutputStream gout = new GZIPOutputStream(bout)) {
gout.write(data.getBytes("ISO-8859-1"));
gout.finish();
return bout.toString("ISO-8859-1");
}
}
ISO-8859-1、流未關閉、字節序錯誤)。getBytes("ISO-8859-1") → GZIPInputStream 解壓 → 字節數組 → 寫文件/返回流。// 服務端
byte[] imgBytes = loadImage(blobFile);
String jsonStr = compress(bytesToString(imgBytes));
// 放入 JSON 字段返回
// 客戶端
byte[] compressed = jsonStr.getBytes("ISO-8859-1");
try (GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed));
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buf = new byte[1024];
int len;
while ((len = gis.read(buf)) != -1) bos.write(buf, 0, len);
byte[] originalImg = bos.toByteArray(); // 還原圖片字節
}
此方案在「不能存文件系統、必須 JSON 內嵌二進制」的受限場景下經驗證可行,關鍵在於 ISO-8859-1 無損字節映射 與 GZIP 節省頻寬 的組合。