首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2EE

JSP 實現資料庫圖片存儲與動態顯示完整實戰

     編輯:J2EE

業務場景:為何將圖片存入資料庫?

  • 資料完整性:圖片與業務資料同庫,避免檔案遺失、路徑錯誤。
  • 事務一致性:圖片與記錄同提交/回滾,無孤兒檔案。
  • 安全性:不直接暴露檔案系統路徑,存取需經應用層授權。
  • 備份簡化:資料庫備份即包含圖片,無需額外檔案同步。

缺點:資料庫體積膨脹、備份/還原耗時、需串流處理效能調優。適用於「圖片量中等、強關聯業務」(如員工照片、產品縮圖、票據影像)。

資料庫表結構設計

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) 高效寫入大二進制物件。

動態圖片輸出 Servlet/JSP

<%@ 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 標籤動態引用

<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> 標籤自動渲染。

效能優化與最佳實踐

  1. 緩衝區大小:byte[4096] 或 8192 平衡記憶體與系統呼叫次數。
  2. 關閉資源順序:ResultSet → Statement → Connection,finally 區塊保證釋放。
  3. MIME 類型偵測:資料庫可額外存 content_type 欄位,動態設定 response.setContentType()。
  4. 大檔案分塊讀寫:避免一次性載入巨大圖片導致 OOM。
  5. 快取策略:加入 response.setHeader("Cache-Control", "max-age=3600") 減少重複請求。
  6. 避免在 JSP 中寫複雜邏輯:建議移至 Servlet 或 Service 層,JSP 僅負責輸出串流。

總結

資料庫存儲圖片的核心流程:上傳 → FileInputStream → setBinaryStream 寫入 → getBinaryStream 讀取 → ServletOutputStream 輸出 → img 標籤引用。掌握二進制流處理、MIME 類型設定與資源管理,即可構建穩健的圖片存儲服務。現代架構建議引入獨立物件存儲,但資料庫方案在中小系統中依具備部署簡單、一致性強的優勢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved