本文共 4892 字,大约阅读时间需要 16 分钟。
主题:使用JAVA读取ORACLE BLOB字段实现上传下载
作者:蔡毅()时间: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这个空对象。 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中调用这个私有方法,完成读取操作。 本文来自CSDN博客,转载请标明出处: