登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - Oracle 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

在Oracle中存取BLOB对象实现文件的上传和下载
发表日期:2005-12-22作者:[转贴] 出处:  

最近做一个J2EE项目,需要在JSP页面实现对文件的上传和下载。很早以前就知道JDBC支持大对象(LOB)的存取,以为很容易,做起来才发现问题多多,读了一大堆文章,反而没有什么头绪了。正如一位网友文章所讲:“…网络上的教程99%都是行不通的,连SUN自己的文档都一直错误……”,实际情况大致如此了。


存取BLOB出现这么多问题,我认为大半是由数据库开发商、应用服务器商在JDBC驱动上的不兼容性带来的。而实际应用中,每个人的开发运行环境不同,使得某个网友的solution没有办法在别人的应用中重现,以至于骂声一片。至于为什么会不兼容、有哪些问题,我没有时间去弄清,这里只说说我们怎样解决了问题的。

 

基于上述原因,先列出我们的开发环境,免得有人配不出来,招人唾骂。

数据库 Oracle 9i

应用服务器 BEA Weblogic 8.11

开发工具 JBuilder X


在JSP实现文件Upload/Download可以分成这样几块 :文件提交到形成InputSteam;InputSteam以BLOB格式入库;数据从库中读出为InputSteam;InputStream输出到页面形成下载文件。先说BLOB吧。


1.  BLOB入库

(1)       直接获得数据库连接的情况

这是Oracle提供的标准方式,先插入一个空BLOB对象,然后Update这个空对象。代码如下:

//得到数据库连接(驱动包是weblogic的,没有下载任何新版本)

Class.forName("oracle.jdbc.driver.OracleDriver");

Connection con = DriverManager.getConnection(

          "jdbc:oracle:thin:@localhost:1521:testdb", "test", "test");

//处理事务

con.setAutoCommit(false);

Statement st = con.createStatement();

//插入一个空对象

st.executeUpdate("insert into BLOBIMG  values(103,empty_blob())");

//用for update方式锁定数据行

ResultSet rs = st.executeQuery(

          "select contents from  BLOBIMG  where  id=103 for update");

if (rs.next()) {

   //得到java.sql.Blob对象,然后Cast为oracle.sql.BLOB

oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob(1).;

   //到数据库的输出流

OutputStream outStream = blob.getBinaryOutputStream();

   //这里用一个文件模拟输入流

File file = new File("d:\proxy.txt");

  InputStream fin = new FileInputStream(file);

//将输入流写到输出流

byte[] b = new byte[blob.getBufferSize()];

        int len = 0;

        while ( (len = fin.read(b)) != -1) {

          outStream.write(b, 0, len);

          //blob.putBytes(1,b);

        }

 

   //依次关闭(注意顺序)

fin.close();

   outStream.flush();

   outStream.close();

   con.commit();

   con.close();


(2)       通过JNDI获得数据库连接

在Weblogic中配置到Oracle的JDBC Connection Pool和DataSource,绑定到Context中,假定绑定名为”orads”。

为了得到数据库连接,做一个连接工厂,主要代码如下:

Context context = new InitialContext();

ds = (DataSource) context.lookup("orads");

return ds.getConnection();

以下是BLOB写入数据库的代码:

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

st.executeUpdate("insert into BLOBIMG values(103,empty_blob())");

ResultSet rs = st.executeQuery(

          "select contents from  BLOBIMG  where  id=103 for update");

if (rs.next()) {

    //上面代码不变

//这里不能用oracle.sql.BLOB,会报ClassCast 异常

weblogic.jdbc.vendor.oracle.OracleThinBlobblob = (weblogic.jdbc.vendor.oracle.OracleThinBlob) rs.getBlob(1);


    //以后代码也不变

OutputStream outStream = blob.getBinaryOutputStream();

File file = new File("d:\proxy.txt");

  InputStream fin = new FileInputStream(file);

byte[] b = new byte[blob.getBufferSize()];

        int len = 0;

        while ( (len = fin.read(b)) != -1) {

          outStream.write(b, 0, len);

        }


fin.close();

   outStream.flush();

   outStream.close();

   con.commit();

   con.close();


2.  BLOB出库

从数据库中读出BLOB数据没有上述由于连接池的不同带来的差异,只需要J2SE的标准类java.sql.Blob就可以取得输出流(注意区别java.sql.Blob和oracle.sql.BLOB)。代码如下:

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

//这里的SQL语句不再需要”for update”

ResultSet rs = st.executeQuery(

          "select contents from  BLOBIMG  where  id=103 ");

if (rs.next()) {

   java.sql.Blob blob = rs.getBlob(1);


   InputStream ins = blob.getBinaryStream();


    //用文件模拟输出流

File file = new File("d:\output.txt");

   OutputStream fout = new FileOutputStream(file);


    //下面将BLOB数据写入文件

    byte[] b = new byte[1024];

    int len = 0;

        while ( (len = ins.read(b)) != -1) {

          fout.write(b, 0, len);

        }

  //依次关闭

  fout.close();

  ins.close();

  con.commit();

  con.close();

 

 

3.  从JSP页面提交文件到数据库


 

(1)       提交页面的代码如下:

<form action="handle.jsp" enctype="multipart/form-data" method="post" >

<input type="hidden" name="id" value="103"/>

<input type="file"  name="fileToUpload">

<input type="submit"  value="Upload">

</form>

 

(2)       由于JSP没有提供文件上传的处理能力,只有使用第三方的开发包。网络上开源的包有很多,我们这里选择Apache Jakarta的FileUpload,在http://jakarta.apache.org/commons/fileupload/index.html 可以得到下载包和完整的API文档。法奥为adajspException

处理页面(handle.jsp)的代码如下

<%

boolean isMultipart = FileUpload.isMultipartContent(request);

    if (isMultipart) {

      // 建立一个新的Upload对象

      DiskFileUpload upload = new DiskFileUpload();

    // 设置上载文件的参数

    //upload.setSizeThreshold(yourMaxMemorySize);

    //upload.setSizeMax(yourMaxRequestSize);

    String rootPath = getServletConfig().getServletContext().getRealPath("/") ;

    upload.setRepositoryPath(rootPath+"\uploads");


     // 分析request中的传来的文件流,返回Item的集合,

     // 轮询Items,如果不是表单域,就是一个文件对象。

      List items = upload.parseRequest(request);

      Iterator iter = items.iterator();

      while (iter.hasNext()) {

        FileItem item = (FileItem) iter.next();

        //如果是文件对象

if (!item.isFormField()) {

          //如果是文本文件,可以直接显示

          //out.println(item.getString());


          //将上载的文件写到服务器的WEB-INFwebstart下,文件名为test.txt

          //File uploadedFile = new File(rootPath+"\uploads\test.txt");

          //item.write(uploadedFile);


        //下面的代码是将文件入库(略):

        //注意输入流的获取

InputStream uploadedStream = item.getInputStream();

        }

        //否则是普通表单

else{

          out.println("FieldName: " + item.getFieldName()+"<br>");

          out.println("Value: "+item.getString()+"<br>");        }

      }

    }

%>

 

4.  从数据库读取BLOB然后保存到客户端磁盘上

这段代码有点诡异,执行后将会弹出文件保存对话窗口,将BLOB数据读出保存到本地文件。全文列出如下:

<%@ page contentType="text/html; charset=GBK" import="java.io.*" import="java.sql.*" import="test.global.ConnectionFactory"%><%

      Connection con = ConnectionFactory.getConnection();

      con.setAutoCommit(false);

      Statement st = con.createStatement();

   ResultSet rs = st.executeQuery(

                     "select contents from  BLOBIMG  where  id=103 ");

      if (rs.next()) {

        Blob blob = rs.getBlob(1);

        InputStream ins = blob.getBinaryStream();

        response.setContentType("application/unknown");

        response.addHeader("Content-Disposition", "attachment; filename="+"output.txt");

        OutputStream outStream = response.getOutputStream();

        byte[] bytes = new byte[1024];

        int len = 0;

        while ((len=ins.read(bytes))!=-1) {

            outStream.write(bytes,0,len);

        }

        ins.close();

        outStream.close();

        outStream = null;

        con.commit();

        con.close();

      }

%>

注意,在<% … … %>之外,绝对不能有任何字符,空格或回车都不行,不然会导致outputStream出错,对非ASCII输出文件来说就是格式错误不可读。

 

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 在Oracle中存取BLOB对象实现文件的上传和下载

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00216