缺點:資料庫體積膨脹、備份/還原耗時、需串流處理效能調優。適用於「圖片量中等、強關聯業務」(如員工照片、產品縮圖、票據影像)。
CREATE TABLE picturenews (
id INT IDENTITY(1,1) PRIMARY KEY,
image IMAGE NULL, -- 二進制圖片資料
content VARCHAR(500) NULL, -- 標題
detail VARCHAR(5000) NULL -- 詳細內容
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];
關鍵點: SQL Server IMAGE 類型(或 MySQL BLOB/LONGBLOB、Oracle BLOB)存儲二進制流。
<form method="POST" action="testimage.jsp" enctype="multipart/form-data">
新聞標題:<input type="text" name="content" /><br/>
新聞圖片:<input type="file" name="image" /><br/>
新聞內容:<textarea name="txtmail" rows="15" cols="90"></textarea><br/>
<input type="submit" value="上傳" />
</form>
必要屬性: enctype="multipart/form-data",否則無法上傳檔案。
<%@ page import="java.sql.*, java.io.*, java.util.*" %>
<%
// 1. 獲取參數(注意編碼轉換)
String content = new String(request.getParameter("content").getBytes("8859_1"), "gb2312");
String detail = new String(request.getParameter("txtmail").getBytes("8859_1"), "gb2312");
String filename = new String(request.getParameter("image").getBytes("8859_1"), "gb2312");
// 2. 讀取檔案輸入流
FileInputStream fis = new FileInputStream(filename);
// 3. 資料庫連線與 PreparedStatement
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:denglu", "sa", "sa");
String sql = "INSERT INTO picturenews (content, image, detail) VALUES (?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, content);
pstmt.setBinaryStream(2, fis, fis.available()); // 關鍵:setBinaryStream
pstmt.setString(3, detail);
pstmt.executeUpdate();
fis.close(); pstmt.close(); con.close();
out.println("圖片存儲成功");
%>
核心 API: PreparedStatement.setBinaryStream(int index, InputStream is, int length) 高效寫入大二進制物件。
<%@ page import="java.sql.*, java.io.*" %>
<%
int id = Integer.parseInt(request.getParameter("id"));
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:denglu", "sa", "sa");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT image FROM picturenews WHERE id=" + id);
if (rs.next()) {
response.setContentType("image/jpeg"); // 關鍵:設定正確 MIME 類型
ServletOutputStream sout = response.getOutputStream();
InputStream in = rs.getBinaryStream(1);
byte[] buffer = new byte[4096];
int len;
while ((len = in.read(buffer)) != -1) {
sout.write(buffer, 0, len);
}
sout.flush();
in.close(); sout.close();
}
rs.close(); stmt.close(); con.close();
%>
儲存為 testimageout.jsp。
<img src="testimageout.jsp?id=1" width="100" height="100" />
<img src="testimageout.jsp?id=<%=rs.getInt("id")%>" width="136" height="99" />
瀏覽器發起 GET 請求,JSP 串流輸出圖片二進制,<img> 標籤自動渲染。
byte[4096] 或 8192 平衡記憶體與系統呼叫次數。content_type 欄位,動態設定 response.setContentType()。response.setHeader("Cache-Control", "max-age=3600") 減少重複請求。資料庫存儲圖片的核心流程:上傳 → FileInputStream → setBinaryStream 寫入 → getBinaryStream 讀取 → ServletOutputStream 輸出 → img 標籤引用。掌握二進制流處理、MIME 類型設定與資源管理,即可構建穩健的圖片存儲服務。現代架構建議引入獨立物件存儲,但資料庫方案在中小系統中依具備部署簡單、一致性強的優勢。