在Web資料庫應用開發中,圖片資訊的存儲與顯示是常見需求。傳統做法是將圖片檔案存放於伺服器特定目錄,資料庫僅記錄檔案路徑。但此法難以滿足動態顯示、權限控管或資料完整性等進階需求。將圖片以二進制流直接存入資料庫,再透過JSP動態讀取輸出,能有效解決上述問題,實現圖片資料的集中管理與靈活調用。
以「圖片新聞」系統為例,我們需要建立資料表來儲存新聞標題、內容及圖片二進制資料。以下為SQL Server的建表腳本:
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[picturenews]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
DROP TABLE [dbo].[picturenews]
GO
CREATE TABLE [dbo].[picturenews] (
[id] [int] IDENTITY(1,1) NOT NULL,
[image] [image] NULL,
[content] [varchar](500) COLLATE Chinese_PRC_CI_AS NULL,
[detail] [varchar](5000) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
欄位說明:
id:主鍵,自動遞增。image:採用 image 資料型別,專門儲存大型二進制圖片資料。content:新聞標題或簡介。detail:新聞詳細內容。建立一個JSP頁面(如 upload.jsp),包含檔案上傳表單。注意表單必須設定 enctype="multipart/form-data"。
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<body>
<form method="POST" action="saveImage.jsp" enctype="multipart/form-data">
新聞標題:<input type="text" name="content" /><br/>
新聞圖片:<input type="file" name="image" /><br/>
新聞內容:<textarea name="detail" rows="10" cols="50"></textarea><br/>
<input type="submit" value="儲存" />
</form>
</body>
</html>
在 saveImage.jsp 中,使用 Part API (Servlet 3.0+) 或 Apache Commons FileUpload 解析請求,獲取輸入流寫入資料庫。以下為核心邏輯示例(使用JDBC PreparedStatement):
<%@ page import="java.sql.*, java.io.*, javax.servlet.*, javax.servlet.http.*" %>
<%
// 1. 獲取上傳檔案輸入流 (此處簡化,實際需解析multipart請求)
Part filePart = request.getPart("image");
InputStream is = filePart.getInputStream();
String content = request.getParameter("content");
String detail = request.getParameter("detail");
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 2. 建立資料庫連線
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver://localhost:1433;databaseName=NewsDB;user=sa;password=123456";
conn = DriverManager.getConnection(url);
// 3. 執行插入
String sql = "INSERT INTO picturenews (content, detail, image) VALUES (?, ?, ?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, content);
pstmt.setString(2, detail);
pstmt.setBinaryStream(3, is, filePart.getSize()); // 寫入二進制流
pstmt.executeUpdate();
out.println("圖片儲存成功!");
} catch (Exception e) {
e.printStackTrace();
out.println("錯誤:" + e.getMessage());
} finally {
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
if (is != null) is.close();
}
%>
建立專門的圖片輸出Servlet或JSP(如 showImage.jsp),從資料庫讀取 Blob 資料並直接輸出至響應流,設置正確的 Content-Type。
<%@ page import="java.sql.*, java.io.*, javax.servlet.*" %>
<%
response.setContentType("image/jpeg"); // 依實際圖片格式調整
String id = request.getParameter("id");
if (id == null || id.trim().isEmpty()) return;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver://localhost:1433;databaseName=NewsDB;user=sa;password=123456";
conn = DriverManager.getConnection(url);
String sql = "SELECT image FROM picturenews WHERE id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, Integer.parseInt(id));
rs = pstmt.executeQuery();
if (rs.next()) {
Blob blob = rs.getBlob("image");
if (blob != null) {
InputStream is = blob.getBinaryStream();
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
}
%>
前端頁面即可透過 <img src="showImage.jsp?id=1" /> 動態顯示資料庫中的圖片。
將圖片以二進制方式存入資料庫,雖會增加資料庫體積,但帶來了資料一致性、備份便利性、存取控制靈活性等優勢。配合JSP/Servlet的流處理機制,可輕鬆實現圖片的動態存取與顯示,是企業級應用常用的架構模式之一。
]]>