使用JAVA讀取ORACLE BLOB欄位實現上傳下載

來源:互聯網
上載者:User

主題:使用JAVA讀取ORACLE BLOB欄位實現上傳下載
作者:蔡毅(caiyi0903@hotmail.com)
時間:2005-6-22

一 BLOB概述

大物件類型BLOB全稱為Binary Large Objects,即二進位大對象。可以把BLOB區別為三種形式:聲像資料、位元據和大文本資料。因此,最常見的應用就是儲存圖形、聲音等對象,此外大二進位對象、OLE對象也可以通過BLOB類型存入資料庫,如果文字物件過大,超出了文本類型的規定長度,則必須用BLOB欄位進行儲存。我們在經常使用的編程環境中並不能直接支援BLOB欄位,因此需要調用相應的函數完成BLOB的使用。

二 實際Struts項目的處理流程

1 插入BLOB欄位的流程

展示層:
上傳使用struts的<html:file property="drawingFile"/>標籤,提交給指定處理的Action,在ActionForm中使用struts內建的FormFile

來儲存檔案。
核心代碼:
<html:form action="/DrawingInputMultiAction" enctype="multipart/form-data">
<html:file property="drawingFile"/>
....省略
</html:form>

控制層:
在Action中將傳入的ActionForm中的檔案欄位賦給VO值對象,並調用業務代理類的上傳方法。
核心代碼:
        //新增
        if(actionType.equals("insert")) {
            //得到檔案類型
            int iFileType = this.getFileType(drawingInputForm.getFileExtendName());
            if(iFileType == 0) {
                //不支援檔案類型
                this.addError(request, "drawing.errors.upload.UnSupportedFileType");
            } else {
                DrawingVO objDrawingVO = new DrawingVO();
                //圖紙基本屬性
                objDrawingVO.setDrawingName(drawingInputForm.getDrawingName());
               ...省略其他set方法

                //執行新增(上傳)
                int iRt = objDrawingMan.insertDrawing(objDrawingVO);
                ...省略
        }

Facade門面:
通過業務代理類調用DAO中的上傳方法,對用戶端完全透明。
    public int insertDrawing(DrawingVO drawingVO) throws ComtopModuleException {
        try {
            DrawingDAO drawingDAO = new DrawingDAO();
            return drawingDAO.insertDrawing(drawingVO);
        } catch(DrawingException ex) {
            throw new ComtopModuleException("drawing.errors.insert", ex);
        }
    }

持久層:
DAO中實現和ORACLE資料庫的底層交涉,完成真正的檔案上傳。
需要先插入一個空BLOB對象,然後Update這個Null 物件。
    public int insertDrawing(DrawingVO drawingVO) throws DrawingException {
        PreparedStatement pstmt = null;
        Statement stmt = null;
        Connection conn = null;
        int iKey = 0;
        ResultSet rs = null;
        //定義SQL語句
        String strSQLInsert = null;
        String strSQLUpdate = null;

        try {
            conn = dataSource.getConnection();
            conn.setAutoCommit(false);
            //插入空BLOB,empty_blob(),其中表中的Content是BLOC類型欄位
            strSQLInsert =
                "insert into PROD_DRAWING (DRAWING_ID, DRAWING_NAME, 省略..." +
                "CONTENT)" +
                "values (?, ?, 省略..., empty_blob())";

            //得到待處理檔案
            FormFile drawingFile = drawingVO.getDrawingFile();

            //插入普通欄位
            pstmt = conn.prepareStatement(strSQLInsert);
            //得到主鍵
            iKey = Toolkit.getInstance().getNextKey(DrawingInfo.ID_STORE_KEY_DRAWING);

            pstmt.setInt(1, iKey);
            ....省略其他set方法

            pstmt.executeUpdate();

            stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                   ResultSet.CONCUR_UPDATABLE);

            strSQLUpdate =
                "SELECT CONTENT FROM PROD_DRAWING WHERE DRAWING_ID ='" +
                iKey + "'" + " FOR UPDATE";

            //讀出記錄以增加圖片Blob欄位
            rs = stmt.executeQuery(strSQLUpdate);

            if(rs.next()) {
                logger.debug("開始寫入BLOB");
                //這裡不能用oracle.sql.BLOB,會報ClassCast異常
                weblogic.jdbc.vendor.oracle.OracleThinBlob blob = (weblogic.jdbc.vendor.
                    oracle.
                    OracleThinBlob)rs.getBlob(1);
                logger.debug("得到輸出資料流");
                OutputStream outStream = blob.getBinaryOutputStream();
                InputStream fin = drawingFile.getInputStream();
                logger.debug("開始分配緩衝");
                byte[] b = new byte[blob.getBufferSize()];
                int len = 0;
                while((len = fin.read(b)) != -1) {
                    logger.debug("正在寫入BLOB流");
                    outStream.write(b, 0, len);
                }
                logger.debug("關閉所有流");
                fin.close();
                outStream.flush();
                outStream.close();
            }
            rs.close();
            conn.commit();
        } catch(Exception ex) {
        ...省略
        }finally {
            DBUtil.destroyDB(rs, pstmt, conn);
        }
        return iKey;
    }

2 讀取BLOB欄位的流程

從資料庫中讀出BLOB資料沒有上述由於串連池的不同帶來的差異,程式流程同插入BLOB欄位,但是讀BLOB就不用那麼複雜了,只需要J2SE的標準類java.sql.Blob就可以取得輸出資料流。

DAO中的核心代碼:
    public DrawingVO readDrawing(int drawingId) throws DrawingException {
        PreparedStatement pstmt = null;
        Connection conn = null;
        DrawingVO objDrawingVO = null;
        ResultSet rs = null;
        //定義SQL語句
        String strSQL = "SELECT * FROM PROD_DRAWING WHERE DRAWING_ID=?";
        try {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(strSQL);
            //設定參數
            pstmt.setInt(1, drawingId);
            //執行查詢
            rs = pstmt.executeQuery();
            while(rs.next()) {
                objDrawingVO = new DrawingVO();
                objDrawingVO.setDrawingId(rs.getInt("DRAWING_ID"));
                objDrawingVO.setDrawingName(rs.getString("DRAWING_NAME"));
               ...省略其他set方法
                //set BLOB到VO中
                objDrawingVO.setContent(rs.getBlob("CONTENT"));
            }
        } catch(Exception ex) {
            ...省略
        }finally {
            DBUtil.destroyDB(rs, pstmt, conn);
        }
        return objDrawingVO;
    }
這樣,傳到Action中VO對象就包含這個BLOB對象了,然後需要在Action中對該對象轉為輸入資料流,可以選擇檔案輸出資料流或Servlet輸出資料流,根據具體情況定,這裡選擇檔案輸出資料流。

核心代碼:
    private String getBlobToFile(Blob blob, DrawingVO objDrawingVO) throws Exception {

        InputStream ins = blob.getBinaryStream();
        //用檔案類比輸出資料流
        String strFileName = objDrawingVO.getDrawingName() + "." +
                             objDrawingVO.getFileExtendName();
        String strRootFilePath = this.getServlet().getServletContext().getRealPath("");
        String strFilePath = "/temp/" + strFileName;
        String contextFilePath = strRootFilePath + strFilePath;
       //定義檔案對象
        File file = new File(this.getServlet().getServletContext().getRealPath("") + "/temp");
        if(!file.exists()) {
            file.mkdir();
        }
        //定義輸出資料流
        OutputStream fout = new FileOutputStream(contextFilePath, true);
        //下面將BLOB資料寫入檔案
        byte[] b = new byte[1024];
        int len = 0;
        while((len = ins.read(b)) != -1) {
            fout.write(b, 0, len);
        }

        //依次關閉
        fout.close();
        ins.close();
        return strFilePath;
    }
最後,在Action中調用這個私人方法,完成讀取操作。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.