DB2保存圖片並讀取動態顯示圖片


博文背景:

客戶要求結構化圖片信息,而不是文件文檔話的管理,故要求將圖片信息存儲於DB2里,出於技術的角度,真不喜歡將文件存儲於數據庫,

但客戶是上帝,木有辦法,故有了如下的測試。

測試環境:DB2 V9.7  JDK7  spring3.x tomcat8

本機測試結果:在第一次訪問的時候動態獲取的速度是直接獲取的1/20的樣子,如果緩存的話就無法對比了。

時間檢測使用了chrome和firfox的F12工具。

 

寫測試代碼的過程中參考了網上很多文章,發現大部分都是copy來copy去,估計都沒去測試過十分能行的通。

這里記錄一下測試過程中遇到的麻煩吧

1、DB2保存的時候數據庫是Blob類型,java里設置成byte[]才能正常保存(BinaryStream和Blob均失敗).

2、讀取DB2的Blob的時候不知道為何使用PreparedStatement讀取不出來,使用Statement才行。

3、IO的操作比較生疏了。

 

表結構:

1、保存圖片

上傳圖片的頁面:

<form action="bs/test/uploadImg.do" method="post" enctype="multipart/form-data" target="testFrame">
        ID:<input type="text" name="id"/><br />
        名字:<input name="name" type="text"/><br />
        文件:<input type="file" name="img"/><br />
        <input type="submit" value="提交"/>
</form>
<iframe src="" id="testFrame" name="testFrame" height="0" width="0" frameborder="0"></iframe>

后台action示例:

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.oreilly.servlet.multipart.FilePart;
import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.ParamPart;
import com.oreilly.servlet.multipart.Part;    
@Urls("uploadImg.do")
@Ajax
public void saveFile(HttpServletRequest request){
    int fileSize = 10;
    try {
        MultipartParser mp = new MultipartParser (request, fileSize * 1024 * 1024 );
        Part part;
        int fileCount = 0;
        byte[] bt = null;
        String name = null;
        String fileName = null;
        String id = "999";
        //遍歷請求中的所有表單
            while((part=mp.readNextPart())!=null){
                 if(part.isFile()){//是文件
                     FilePart fp = (FilePart)part;
                     fileName = fp.getFileName();
                     if (fileName.endsWith("png") || fileName.endsWith("gif") || fileName.endsWith("jpg") || fileName.endsWith("jpeg")) {
                         //輸出流的目的是將輸入流轉成byte數組
                         ByteArrayOutputStream out = new ByteArrayOutputStream();
                         InputStream in = fp.getInputStream();
                         int size = 0;
                         byte[] buffer = new byte[1024];
                         while((size=in.read(buffer))!=-1){
                             out.write(buffer, 0, size);
                         }
                         bt = out.toByteArray();
                         fileCount++;
                     }else {
                        throw new Exception("文件不是圖片!");
                    }
                 }else{
                    ParamPart pp = (ParamPart)part;
                    String inputName = pp.getName();
                    if("name".equals(inputName)){
                        name = pp.getStringValue();
                    }else if("id".equals(inputName)){
                        id = pp.getStringValue();
                    }
                 }
            }
            if(fileCount==0){
                throw new Exception("請選擇圖片后再上傳!");
            }
            this.testDao.saveFile(fileName, bt, name,Integer.parseInt(id));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

dao方法:

public void saveFile(final String fileName,final byte[] bt,final String name,final int id) throws SQLException{
        String sql = "insert into SDE.T_TEST_IMG(ID,FILE_NAME,IMG_FILE,NAME) VALUES(?,?,?,?)";
        
        this.getJdbcTemplate().update(sql, new PreparedStatementSetter() {
            public void setValues(PreparedStatement ps) throws SQLException {
                ps.setInt(1, id);
                ps.setString(2, fileName);
                //下面這2種都會報錯,網上一大堆例子都是這么寫的,很詫異..............
                //ps.setBinaryStream(3, fis, fileSize);
                //ps.setBlob(3, fis);
                ps.setBytes(3, bt);
                
                ps.setString(4, name);
            }
        });
    }

 

2、讀取圖片

前台:

<input type="button" onclick="setUrl()" value="加載圖片"/>
    
<img src="" alt="動態生成" id="dImg"/>
<img src="" alt="直接獲取" id="sImg"/>

js:

function setUrl(){
//動態生成同樣的圖片
document.getElementById("dImg").src="generationImg?id=3";
//直接訪問圖片
document.getElementById("sImg").src="mobileImage/17074_20130927160025.jpg";
}

處理生成圖片的servlet:

/**
     * 從數據庫里讀取Blob類型的圖片並顯示給前台
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id = request.getParameter("id");
        response.setContentType("image/jpeg");
        TestDao testDao = (TestDao)WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext()).getBean(TestDao.class);
        InputStream ins = null;
        try {
            ins = testDao.loadFile(id);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //從輸入流構建圖片
        BufferedImage image = null;
        image = ImageIO.read(ins);
        ServletOutputStream out = response.getOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        encoder.encode(image);
        
        ins.close();
        out.flush();
        out.close();
    }

dao方法:

/**
     * 讀取DB2的blob字段並轉換成流
     * @param id
     * @return
     * @throws SQLException
     */
    public InputStream loadFile(String id) throws SQLException{
        String sql = "select IMG_FILE from SDE.T_TEST_IMG where ID="+id;
        InputStream ins = null;
        
        Connection con = this.getJdbcTemplate().getDataSource().getConnection();
        Statement ps = con.createStatement();
        ResultSet rs = ps.executeQuery(sql);
        while(rs.next()){
            Blob blob = rs.getBlob("IMG_FILE");
            ins = blob.getBinaryStream();
        }
        return ins;
        
        //下面這個寫法會有問題,而且上面那個Statement改成PrepareStatement后也獲取不到值,ResultSet是null
        /*
           InputStream ins = this.getJdbcTemplate().execute(sql, new PreparedStatementCallback() {

            public Object doInPreparedStatement(PreparedStatement ps)
                    throws SQLException, DataAccessException {
                ResultSet rs = ps.getResultSet();
                Blob blob = rs.getBlob(1);
                InputStream ins = blob.getBinaryStream();
                return ins;
            }
        });
        return ins;*/
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM