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的操作比较生疏了。

 

表结构:

DB2保存图片并读取动态显示图片

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;*/

    }

你可能感兴趣的:(db2)