1. 程式人生 > >如何處理BLOB型別資料之三:使用Servlet在頁面上顯示BLOB中的圖片

如何處理BLOB型別資料之三:使用Servlet在頁面上顯示BLOB中的圖片

實驗環境:JDeveloper 11.1.2.0.0。
接上一個實驗《如何處理BLOB型別資料之二:下載BLOB內容並儲存到檔案中》。

我的設計思想:
這其實是一個動態顯示圖片的問題,類似於很多網站上登入時要求輸入的圖片認證碼。
一開始,根據前面的思路,我打算繼續使用ADF BC的來顯示BLOB中的圖片內容,後來發現這個功能相對來說比較獨立,於是就想寫一個通用的,這樣沒有ADF也可以使用。
於是,我參考了《一個讀取BLOB中圖片的Servlet程式碼》,寫了一個Servlet。

1. 新建頁面:get_image_from_blob.jspx
<af:image source="/blobimageservlet?id=75" id="i5"/>

我這裡只是測試Servlet是否工作正常,因此引數id給的是常量75,因為我上傳的id=75的檔案是一個.jpg。
你可以根據你的需要,把引數動態設定。

2. 建立Servlet:BlobImageServlet.java
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;

import java.io.PrintWriter;

import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import javax.sql.DataSource;

public class BlobImageServlet extends HttpServlet {
private static final String CONTENT_TYPE = "image/jpg; charset=utf-8";

public void init(ServletConfig config) throws ServletException {
super.init(config);
}

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
String idStr = request.getParameter("id");
int id = -1;
if (idStr != null) {
id = Integer.parseInt(idStr);
}

OutputStream os = response.getOutputStream();
Connection conn = null;

try {
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/uploadFileToBlobConnDS");
conn = ds.getConnection();
PreparedStatement statement =
conn.prepareStatement("SELECT UploadedFiles.ID," + 
" UploadedFiles.FILENAME, " +
" UploadedFiles.CONTENT " + 
"FROM UPLOADED_FILES UploadedFiles " +
"WHERE UploadedFiles.ID = ?");

statement.setInt(1, new Integer(id));
ResultSet rs = statement.executeQuery();
if (rs.next()) {
Blob blob = rs.getBlob("Content");
BufferedInputStream in = new BufferedInputStream(blob.getBinaryStream());
int b;
byte[] buffer = new byte[10240];
while ((b = in.read(buffer, 0, 10240)) != -1) {
os.write(buffer, 0, b);
}
os.close();
}
} catch (Exception e) {
e.printStackTrace(); 
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException sqle) {
System.out.println("SQLException error");
}
}
}
}

3. 執行,訪問get_image_from_blob.jspx,顯示BLOB中的圖片內容
唉,斯人已逝,永遠懷念的鄧麗君......


4. 深入分析
使用Servlet來顯示BLOB中的圖片內容,可能會引起效能問題。因為每一個BLOB圖片顯示,都要佔用一個數據庫連線。
可以考慮修改Serverlt的邏輯如下:
如果在某個路徑下沒有某個圖片,那麼,再去訪問資料庫,獲取圖片,並生成在該路徑下。
否則,直接訪問已經生成的圖片檔案。
其中,為了保證圖片名稱的唯一性,圖片名稱包含時間戳。

5. 問題:如果使用ADF BC該如何做?
我認為在某些情況下,使用ADF BC還是比較方便的,比如一個天氣預報表格中,某一列用小圖片來表示不同的天氣情況。
因為省去了連線資料庫的程式碼,不會有效能問題。
而且可以非常方便的獲取BlobDomain物件:row.Content。如果支援如下寫法就更好了:
<af:image source="#{row.Content}" id="i5"/>
可惜這樣寫,是無法顯示出圖片的。
可以在Managed Bean中寫一個方法來處理BlobDomain,放到image的source屬性中。
這個以後有空在寫吧。

Project 下載:UploadFileToBlob_DownloadBlobToFile_getBlobImage.7z

參考文獻:

1. http://kr.forums.oracle.com/forums/thread.jspa?threadID=614954。

http://maping930883.blogspot.com/2011/08/adf097blobblob.html