zoukankan      html  css  js  c++  java
  • 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;*/
        }
  • 相关阅读:
    华为云垃圾分类大赛,让AI 帮你“见圾行事”
    【带着canvas去流浪(14)】Three.js中凹浮雕模型的生成方式
    Ubuntu 配置网卡信息
    配置 Mysql 支持远程访问 并取消域名解析以提高链接速度
    jQuery 操作 html5 data-* 属性
    Laravel 中使用原生的 PHPExcel
    Laravel 上使用 phpexcel的两种方式
    debian中默认不存在sudo命令解决方法
    composer install 时,提示:Package yiisoft/yii2-codeception is abandoned, you should avoid using it. Use codeception/codeception instead.的解决
    Linux 磁盘分区存放文件和目录的数量 (inode)
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/3794001.html
Copyright © 2011-2022 走看看