博文背景:

客户要求结构化图片信息,而不是文件文档话的管理,故要求将图片信息存储于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. C/C++ 函数指针 总结

    什么是函数指针 就像某一变量的地址可以存储在相应的指针变量中一样,指向函数的指针中保存着函数代码起始处的地址 函数指针的声明 当声明一个函数指针时,必须声明它指向的函数类型.要指定函数类型,就要指出函 ...

  2. Android 官方文档:(一)动画和图像 —— 1.5 画布和画图

    The Android framework APIs provides a set 2D drawing APIs that allow you to render your owncustom gr ...

  3. Thinkpad T440p安装Linux的种种问题(by quqi99)

    作者:张华  发表于:2014-05-08 版权声明:能够随意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (http://blog.csdn.net/quqi99 ) Thi ...

  4. 转 UIAlertView 不显示、屏幕变灰

    UIAlertView 不显示.屏幕变灰 SvenFang 票 在 [[NSNotificationCenter defaultCenter] addObserver:self selector:@s ...

  5. java 实现好看的图形验证码

    package com.invoice.utils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.Aff ...

  6. unity3d摄像机参数

    1. Clear Flags:清除标记.决定屏幕的哪部分将被清除.一般用户使用对台摄像机来描绘不同游戏对象的情况,有3中模式选择: Skybox:天空盒.默认模式.在屏幕中的空白部分将显示当前摄像机的 ...

  7. 结合MapReduce和数据集Combining datasets with MapReduce

    While in the SQL-world is very easy combining two or more datasets - we just need to use the JOIN ke ...

  8. 【BZOJ】【3611】【HEOI2014】大工程

    虚树+树形DP 本题100W的点数……不用虚树真的好吗…… Orz ZYF 我的感悟: dp的过程跟SPOJ 1825 FTOUR2 的做法类似,依次枚举每个子树,从当前子树和之前的部分中各找一条最长 ...

  9. Kmeans聚类算法分析(转帖)

    原帖地址:http://www.opencvchina.com/thread-749-1-1.html       k-means是一种聚类算法,这种算法是依赖于点的邻域来决定哪些点应该分在一个组中. ...

  10. Javascript模块化工具require.js教程

    转自:http://www.w3cschool.cc/w3cnote/requirejs-tutorial-1.html, http://www.w3cschool.cc/w3cnote/requir ...