博文背景:

客户要求结构化图片信息,而不是文件文档话的管理,故要求将图片信息存储于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;*/
}

DB2保存图片并读取动态显示图片的更多相关文章

  1. window.open()读取本地图片简单使用总结

    最近做了一个项目,需要读取本地图片出来,问了一些人,感觉在数据库中存取路径比较合适,故做此方法. 后台查询出来的路径

  2. 【原创】Android 4.4前后版本读取图库图片方式的变化

    Android 4.4前后版本读取图库图片方式的变化   本文讲述Android 4.4(KitKat)前后访问图库以及访问后通过图片路径读取图片的变化   Android 4.4(KitKat)以前 ...

  3. matlab读取多幅图片,并对读取的图片降采样和双三次插值

    clear all clc im = {}; %%创建字典im以保存读取的图片 dis = dir('C:\Users\KCl\Documents\MATLAB\SRCNN\Set5\*.bmp'); ...

  4. 与众不同 windows phone (16) - Media(媒体)之编辑图片, 保存图片到相册, 与图片的上下文菜单“应用程序...”和“共享...”关联, 与 Windows Phone 的图片中心集成

    原文:与众不同 windows phone (16) - Media(媒体)之编辑图片, 保存图片到相册, 与图片的上下文菜单"应用程序..."和"共享..." ...

  5. C#从SQL server数据库中读取l图片和存入图片

    原文:C#从SQL server数据库中读取l图片和存入图片 本实例主要介绍如何将图片存入数据库.将图片存入数据库,首先要在数据库中建立一张表,将存储图片的字段类型设为Image类型,用FileStr ...

  6. js读取本地图片并显示

    抄自 http://blog.csdn.net/qiulei_21/article/details/52785191 js读取本地图片并显示 第一种方法比较好 版权声明:本文为博主原创文章,未经博主允 ...

  7. [转]opengl入门例题(读取bmp图片,并显示)

    #include<gl/glut.h> #define FileName "bliss.bmp" static GLint imagewidth; static GLi ...

  8. java读取网页图片路径并下载到本地

    java读取网页图片路径并下载到本地 最近公司需要爬取一些网页上的数据,自己就简单的写了一个demo,其中有一些数据是图片,需要下载下来到本地并且 将图片的路径保存到数据库,示例代码如下: packa ...

  9. OpenGL使用libPng读取png图片

    #include<stdarg.h> #include<png.h> #include<glut.h> #include<math.h> #includ ...

随机推荐

  1. mormot当作内存数据库(缓存)使用

    mormot当作内存数据库(缓存)使用 mormot的TSQLRestStorageInMemory可以作为内存数据库来使用. 上图是在笔者4代I5笔记本上做的测试,增加10万记录,耗时:562毫秒. ...

  2. IE中Ext的comboBox跑到页面左上角

    { xtype:'combo', width:100, //id:'exTypeCom', name:'exType', hiddenName:'exType', displayField:'text ...

  3. ExtJs动态生成复选框

    var old_value = Ext.get("fgzr_select").getValue() if(old_value == ""){ document. ...

  4. javax.mail 遇到501 mail from address must be same as authorization user 的問題

    使用不同的兩個帳戶发送email时,第一个账户可以发送成功,但到第二个账户的时候就报出了501 mail from address must be same as authorization user ...

  5. 关于OpenLDAPAdmin管理页面提示“This base cannot be created with PLA“问题. Strong Authentication Required问题

    经过查询,最终总结和处理如下: 1.首先需要在/etc/openldap/目录下,创建一个base.ldif文件,如下所示: 2.在base.ldif文件中,写入如下信息,为创建初始化根节点做准备工作 ...

  6. CAS工作流程

    CAS3.0的工作流程: 0.app将用户转发到CAS处, 并将自己的url作为callback参数传给CAS. 1.CAS验证用户成功(authentication) 2.生成用户实体(princi ...

  7. easyui datatimebox 取值和赋值

    1.取值 var time = $('.easyui-datetimebox').datetimebox('getValue'); 全部代码如下: <script type="text ...

  8. C#中属性PropertyInfo的使用

    昨天编程遇到一个问题两个类字段都是二十多个,其中有十多个是相同的,需要将一个类的字段赋值给另外一个类,开始的自己想手动的一个个去赋值,后来想来一下C#基础知识,用PropertyInfo就可以解决类似 ...

  9. Retrofit 从入门到了解【总结】

    源码:https://github.com/baiqiantao/RetrofitDemo.git 参考:http://www.jianshu.com/p/308f3c54abdd Retrofit入 ...

  10. Javascript 操作 Sql中的Xml 字段

    在一个项目当中,我们需要把数据库中的Xml字段中的信息表现在页面中,如果用Sql进行操作,读取.这样的话,必然导致太复杂,于是我想到了,如果把Xml字段先读出来,然后用Js去操作,这样岂不是简单了许多 ...