首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 存儲圖片實戰:BLOB + BFILE + DBMS_LOB 完整流程

     編輯:Oracle 資料庫基礎

在資料庫中儲存圖片等二進位檔案,Oracle 推薦使用 BLOB (Binary Large Object) 資料型別,配合 DBMS_LOB 套件與 BFILE (外部檔案參照) 實現高效、安全的檔案載入。本文提供從建表、建立目錄物件、撰寫載入 Procedure、到 Java 端讀取顯示的完整端到端範例。

資料庫端完整步驟

1. 建立儲存表 (BLOB 欄位)

CREATE TABLE image_lob (
  t_id    VARCHAR2(5) NOT NULL,
  t_image BLOB        NOT NULL
);

2. 建立 Directory 物件 (對應 OS 目錄)

-- 需 CREATE ANY DIRECTORY 權限 (通常由 DBA 執行)
CREATE OR REPLACE DIRECTORY images AS 'C:\Oracle\Images';
-- Linux 範例:CREATE OR REPLACE DIRECTORY images AS '/u01/app/oracle/images';

注意:目錄路徑必須為資料庫伺服器端可存取的實體路徑,非 Client 端路徑。

3. 建立圖片載入 Procedure

CREATE OR REPLACE PROCEDURE img_insert (
  p_tid     IN VARCHAR2,
  p_filename IN VARCHAR2
) AS
  v_bfile  BFILE;
  v_blob   BLOB;
BEGIN
  -- 1. 插入空 BLOB 並取得 LOB Locator
  INSERT INTO image_lob (t_id, t_image)
  VALUES (p_tid, EMPTY_BLOB())
  RETURNING t_image INTO v_blob;

  -- 2. 建立 BFILE 指向外部檔案
  v_bfile := BFILENAME('IMAGES', p_filename);  -- 目錄物件名 + 檔名

  -- 3. 唯讀開啟外部檔案
  DBMS_LOB.FILEOPEN(v_bfile, DBMS_LOB.FILE_READONLY);

  -- 4. 將檔案內容載入 BLOB (一次性載入全長)
  DBMS_LOB.LOADFROMFILE(
    dest_lob => v_blob,
    src_lob  => v_bfile,
    amount   => DBMS_LOB.GETLENGTH(v_bfile)
  );

  -- 5. 關閉外部檔案
  DBMS_LOB.FILECLOSE(v_bfile);

  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    IF DBMS_LOB.FILEISOPEN(v_bfile) = 1 THEN
      DBMS_LOB.FILECLOSE(v_bfile);
    END IF;
    ROLLBACK;
    RAISE;
END img_insert;
/

4. 執行載入測試

-- 將 C:\Oracle\Images\f_TEST.jpg 載入 ID='1'
EXEC img_insert('1', 'f_TEST.jpg');

Java 端讀取與顯示 (Servlet 範例)


public class ImageServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {

    String imgId = req.getParameter("id");  // 如 ?id=1
    if (imgId == null) { resp.sendError(400); return; }

    String sql = "SELECT t_image FROM image_lob WHERE t_id = ?";

    try (Connection conn = DataSourceUtil.getConnection();
         PreparedStatement ps = conn.prepareStatement(sql)) {

      ps.setString(1, imgId);
      try (ResultSet rs = ps.executeQuery()) {
        if (rs.next()) {
          Blob blob = rs.getBlob("T_IMAGE");
          if (blob != null) {
            resp.setContentType("image/jpeg");  // 依實際格式調整
            resp.setContentLengthLong(blob.length());

            try (InputStream is = blob.getBinaryStream();
                 OutputStream os = resp.getOutputStream()) {
              byte[] buffer = new byte[8192];
              int len;
              while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
              }
            }
            return;
          }
        }
      }
    } catch (SQLException e) {
      throw new ServletException("DB error", e);
    }
    resp.sendError(404);
  }
}

關鍵技術點總結

元件角色關鍵方法
BLOB資料庫內部儲存二進位資料EMPTY_BLOB(), RETURNING INTO
BFILE指向伺服器外部檔案的只讀指標BFILENAME(dir, file), FILEOPEN/FILECLOSE
DBMS_LOBLOB 操作核心套件LOADFROMFILE, GETLENGTH, READ/WRITE
DIRECTORY邏輯目錄物件,隔離 OS 路徑CREATE DIRECTORY, GRANT READ ON DIRECTORY

效能與安全建議

  1. 大檔案分塊讀寫:超過 1GB 建議使用 DBMS_LOB.READ/WRITE 分塊處理,避免 PGA 記憶體暴增。
  2. 啟用 SecureFiles (11g+):CREATE TABLE ... (t_image BLOB STORE AS SECUREFILE) 享有壓縮、重複刪除、加密、緩存優化。
  3. 權限最小化:僅對應用帳號 GRANT READ ON DIRECTORY images TO app_user;,不給 WRITE。
  4. 備份考量:BLOB 會隨資料庫備份 (RMAN) 完整備份;若檔案極大量,考慮僅存路徑 (檔案系統/物件儲存) 而非資料庫內部。
  5. Content-Type 識別:資料庫不存 MIME 類型,建議表中增加 mime_type VARCHAR2(50) 欄位,或由副檔名推斷。

掌握 BFILE → DBMS_LOB.LOADFROMFILE → BLOB 這條標準鏈路,即可在 Oracle 中安全、高效地管理圖片等非結構化資料。

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