请教,数据微信帖子的窗口照片怎么显示blob型的照片

关于blob对象(图片)的缓存和提取问题 - ITeye问答
前段时间给客户做了一个会议签到系统
系统中涉及到这么一个问题:
用户签到的时候有一个页面显示当前签到人的照片和最近签到的6个人的照片,
照片数据都以blob对象存储在数据库中的,
为了在页面上显示照片,我直接写了一个servlet来处理照片的请求,
servlet中直接把blob二进制流输出给jsp界面。
jsp以&img src="/conference/image" height="280" width="200"&的形式向servlet发送请求来获取照片
servlet中以
ServletOutputStream out = res.getOutputStream();
Blob temp = photo.getPhoto();
InputStream is = temp.getBinaryStream();
byte buffer[] = new byte[256];
while (is.read(buffer, 0, 256) != -1) {
out.write(buffer);
}
out.flush();
的形式响应。
每当有人签到,jsp页面就自动刷新一次来获取新的6张照片
这样设计有几个瓶颈
1、照片本身大小比较大,每张都是200+k,每次刷新所有的照片都要重新到后台去获取,对网络的要求比较高,而且如果多个人同时使用这个页面刷新的话,更是问题
2、每次请求的blob数据都需要到后台数据库中取数据,而且都是 并发的请求,对数据库的连接和数据库都有很大的压力,容易使服务down了
试着改进过,因为每次请求的6张照片中正常情况有5张是重复的,所以我想用hashmap把查出来的结果缓存起来,下次有请求来了,如果在缓存中有了,就直接在缓存中取。没有再到数据库中取,缓存中到了一定数量,再把缓存全部清了,否则肯定会占用大量内存。
但是这样又有问题,java的回收机制自动把我hashmap中的blob对象给清掉了。每次取到的persistence是有的可是到persistence中取blob却是空的了。所以jsp界面显示的照片都是空的。
不知道有没有高人能提出一个好的解决方案。探讨探讨,如何改进。或者重新设计。
不胜感激!
问题补充:HashMap问题blob对象被清& 是这样的
HashMap本来就是放在单子实例中的,肯定也是static
public class AnalyseDAO extends BasicDAO {
private static AnalyseDAO _instance= new AnalyseDAO();;
public static AnalyseDAO getInstance() {
&&& if (_instance == null) {
&&&&&&& _instance = new AnalyseDAO();
& }
&&& return _
}
private static HashMap photohash = new HashMap();
public TCifPhoto getCifPhoto(String stuempNo){
if(photohash.size()&=50){
& photohash.clear();
}
if(photohash!=null && photohash.get(stuempNo)!=null){
& TCifPhoto tmp= (TCifPhoto)photohash.get(stuempNo);
& if(tmp.getPhoto()==null){
& System.out.println("omg& that's it lob is empty");
}
}else{
& Session s = getSession();
& String sql = " from TCifPhoto cif where cif.stuempNo= '"+stuempNo+"'";
try {
& Query q = s.createQuery(sql);
& List list = q.list();
& if(list!=null&&list.size()&0){
& return (TCifPhoto)list.get(0);
}else{
&
}
} catch (HibernateException he) {
&
}
}
这样的设计在tomcat上跑一点问题都没有& HashMap中的数据也能取到,可是一但到websphere上HashMap中存储的TCifPhoto 这个persistence还在,就是persistence里面的二进制lob对象没有了,从代码里看出系统输出了“omg& that's it lob is empty”就很明显知道问题的状况。可以判定websphere把lob字段给清了。
或者另一种架设是websphere用到了对lob字段的lazyload的方式或者别的。没有找到相应的文档资料。问题补充:又补充讨论一下:
现在看来armorking说的应该是对的,blob的操作是逻辑指针,数据库连接释放后就不能取到值了。而tomcat和websphere数据库连接的管理方式又别,所以同样的代码,tomcat能正常运行,websphere就不行。(这有待继续挖掘区别,o(∩_∩)o...)。
其实把blob缓存,我觉得不是最好的方案吧,即时做成byte[]缓存解决了原先的问题,但是,每张图片有300k,在签到峰值时期,每个用户客户端与服务器的网络流量将达到很高的程度,假设刷新为2s一次 300K*6=1.8M ,接近1M/s。再加上如果有多个客户端在刷。服务器流量将受到考验。
所以我考虑是不是可以把照片缓存到每个客户端ie缓存中。首先把第一次请求的照片数据从数据库中取出缓存到服务器硬盘上。而客户端直接通过url来存取服务器上的照片。每次刷新后,相同的照片ie会自动取ie缓存中的照片,而不会再到服务器上取,这样就能解决原来的两个问题了。
不知道大家有什么建议?
采纳的答案
从lz提供的source来看
blob数据检索出来以后,并没有被放到photohash中
另外,根据sql的Blob的文档
引用
默认情况下,驱动程序使用 SQL locator(BLOB) 实现 Blob,这意味着 Blob 对象包含一个指向 SQL BLOB 数据而不是数据本身的逻辑指针。Blob 对象在它被创建的事务处理期间有效。
TCifPhoto.getPhoto()的类型如果是Blob型而不是 byte[]的话,
一旦检索事务处理结束了,的确有可能变成null
这样的情况就有点妖了,按理说只要不是操作系统不一致,java虚拟机的本地实现应该是一致的。
缓存图片信息的字节数组看看?
以我的理解,这个问题跟垃圾回收无关
一般来说,对象在servlet中有三种scope:
request, session, application
其中request & session & application
而lz想做的应该是个对象缓存
但是每个用户的session是不同的,也就是说不同用户的session是无法共享的
所以,应当使用application级别的缓存策略
从实现手段上来讲,最简单的,就是一个单例类就能搞定
只需要注意两点:
1、既然是个“会议签到系统”,那么这个缓存的结构就应该是一个会议对应一个照片缓存
2、每次用户签到后缓存的6个相片中最早签到的一张需要被最新签到的用户照片替换
这个替换处理需要加上同步处理
3、根据实际应用场景,可能需要对缓存做清除处理
比如说这个“会议签到系统”应当会对会议的状态管理中有一个“会议结束”的处理
那么,在这个“会议结束”处理的最后,应当把对应的缓存清除
一般情况下,垃圾回收不会去主动清除仍然存在Map中引用的对象,除非是WeakHashMap等特殊的Map实现。
建议你检查下代码,看缓存的HashMap是否static。
每个不同的照片都有个名字吧?相同的相片的名字总是相同吧?
用客户端缓存不行吗?相片缓存久点就是了嘛。这样只有初次访问的时候可能会消耗些时间。当每个人的相片都缓存了之后,就不会消耗多少资源了。
引用但是这样又有问题,java的回收机制自动把我hashmap中的blob对象给清掉了。每次取到的persistence是有的可是到persistence中取blob却是空的了。所以jsp界面显示的照片都是空的。
你肯定是把HashMap丢在Servlet中了, 丢在某个单件类中 [就一个系统运行的话] 或者 丢在Session中[多个系统的话].
把照片放在server的硬盘上吧,显示照片根据签会人的id显示6张照片好了。
不过现在你可以把硬盘上不存在的照片从库里读出来,要是硬盘上有,下次就不用读库了。
已解决问题
未解决问题Oracle中插入图片并显示(用BLOB类型)
中插入图片并显示(用BLOB类型)
要在oracle里面存入图片 用 blob类型
首先在里建立:
--连接到管理员
--为scott用户授权
grant create an
--回到scott用户
conn scott/
--创建存储图片的表
CREATE TABLE IMAGE_LOB (T_ID VARCHAR2 (5) NOT NULL,T_IMAGE BLOB NOT NULL);
--创建存储图片的目录
CREATE OR REPLACE DIRECTORY IMAGES AS 'C:\picture';
--在c:下自己建一个叫picture的文件夹
CREATE OR REPLACE PROCEDURE IMG_INSERT (TID VARCHAR2,FILENAME VARCHAR2) AS
F_LOB BFILE;--文件类型
B_LOB BLOB;
iNSERT INTO IMAGE_LOB (T_ID, T_IMAGE)
VALUES (TID,EMPTY_BLOB ()) RETURN T_IMAGE INTO B_LOB;
--插入空的blob
F_LOB:= BFILENAME ('IMAGES', FILENAME);
--获取指定目录下的文件
DBMS_LOB.FILEOPEN(F_LOB, DBMS_LOB.FILE_READONLY);
--以只读的方式打开文件
DBMS_LOB.LOADFROMFILE (B_LOB, F_LOB,DBMS_LOB.GETLENGTH (F_LOB));
--传递对象
DBMS_LOB.FILECLOSE (F_LOB);
--关闭原始文件
--在C:\picture下放一张图片1.gif
--将该图片存入表
call IMG_INSERT('1','1.gif');
然后创建一个web项目 连接数据库后 创建一个BlobDAO类 用来取出表中的blob类型图片
代码& 收藏代码
&&& public class BlobDAO {&
&&&&&&& private static final BlobDAO instance = new BlobDAO();&
&&&&&&& private Connection conn =&
&&&&&&& private BlobDAO() {&
&&&&&&& }&
&&&&&&& public static BlobDAO getInstance() {&
&&&&&&&&&&&&
&&&&&&& }&
&&&&&&& private void initConn() {&
&&&&&&&&&&& conn = DBAccess.getInstance().getConn();&
&&&&&&& }&
&&&&&&& public byte[] getImage(String imgname) {&
&&&&&&&&&&& BufferedInputS//取得BLOB的IO流&
&&&&&&&&&&& byte[] bt =&
&&&&&&&&&&& initConn();&
&&&&&&&&&&& Blob bo =&
&&&&&&&&&&& PreparedStatement ps =&
&&&&&&&&&&& ResultSet rs =&
&&&&&&&&&&& String sql = &select T_IMAGE from IMAGE_LOB where t_id=?&;&
&&&&&&&&&&& try {&
&&&&&&&&&&&&&&&&& ps = conn.prepareStatement(sql);&
&&&&&&&&&&&&&&&&& ps.setString(1, imgname);&
&&&&&&&&&&&&&&&&& rs = ps.executeQuery();&
&&&&&&&&&&&&&&&&& if (rs.next()) {&
&&&&&&&&&&&&&&&&&&&&& bo = rs.getBlob(&T_IMAGE&);&
&&&&&&&&&&&&&&&&&&&&& try {&
&&&&&&&&&&&&&&&&&&&&&&&&& ins = new BufferedInputStream(bo.getBinaryStream());&
&&&&&&&&&&&&&&&&&&&&&&&&& int bufferSize = (int) bo.length();//取得BLOB的长度&
&&&&&&&&&&&&&&&&&&&&&&&&& bt = new byte[bufferSize];&
&&&&&&&&&&&&&&&&&&&&&&&&& try {&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ins.read(bt, 0, bufferSize);&
&&&&&&&&&&&&&&&&&&&&&&&&& } catch (IOException e) {&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& e.printStackTrace();&
&&&&&&&&&&&&&&&&&&&&&&&&& }&
&&&&&&&&&&&&&&&&&&&&&&&&& //建立字节缓存&
&&&&&&&&&&&&&&&&&&&&& } catch (SQLException e) {&
&&&&&&&&&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block&
&&&&&&&&&&&&&&&&&&&&&&&&& e.printStackTrace();&
&&&&&&&&&&&&&&&&&&&&& }&
&&&&&&&&&&&&&&&&& }&
&&&&&&&&&&& } catch (SQLException e) {&
&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block&
&&&&&&&&&&&&&&&&& e.printStackTrace();&
&&&&&&&&&&& } finally {&
&&&&&&&&&&&&&&&&& try {&
&&&&&&&&&&&&&&&&&&&&& rs.close();&
&&&&&&&&&&&&&&&&&&&&& ps.close();&
&&&&&&&&&&&&&&&&&&&&& conn.close();&
&&&&&&&&&&&&&&&&& } catch (SQLException e) {&
&&&&&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block&
&&&&&&&&&&&&&&&&&&&&& e.printStackTrace();&
&&&&&&&&&&&&&&&&& }&
&&&&&&&&&&& }&
&&&&&&&&&&&&
&&&&&&& }&
在action里面调用getImage()方法并显示图片在页面上
Java代码& 收藏代码
&&& public ActionForward execute(ActionMapping mapping, ActionForm form,&
&&&&&&&&&&&&&&&&& HttpServletRequest request, HttpServletResponse response) {&
&&&&&&&&&&& // TODO Auto-generated method stub&
&&&&&&&&&&&&&
&&&&&&&&&&& BlobDAO blobDAO = BlobDAO.getInstance();&
&&&&&&&&&&&&&
&&&&&&&&&&& byte[] bs = blobDAO.getImage(&1&);&
&&&&&&&&&&&&&
&&&&&&&&&&& try {&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&& response.getOutputStream().write(bs);&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&& } catch (IOException e) {&
&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block&
&&&&&&&&&&&&&&&&& e.printStackTrace();&
&&&&&&&&&&& }&
&&&&&&&&&&&&&
&&&&&&&&&&&&
&&&&&&& }&
添加图片到数据库
请在c盘下放入图片--c:\\4.gif
Java代码& 收藏代码
& public void savaImg(String imgId) {
&&&&&&&&&& //传的是存入数据库图片的id
&&&&&&&&&& initConn();
&&&&&&&&&& Statement st =
&&&&&&&&&& BLOB blob = //图片类型
&&&&&&&&&& OutputStream outputStream = //输出流
&&&&&&&&&& File file = //文件
&&&&&&&&&& InputStream inputStream = //输入流
&&&&&&&&&& ResultSet rs =
&&&&&&&&&& try {
&&&&&&&&&&&&&&&& conn.setAutoCommit(false); //事物由程序员操作
&&&&&&&&&&&&&&&& st = conn.createStatement();
&&&&&&&&&&&&&&&& st.executeQuery(&insert into IMAGE_LOB values('&+ imgId +&',empty_blob())&);
&&&&&&&&&&&&&&&& rs = st.executeQuery(&select T_IMAGE from IMAGE_LOB where t_id='&+ imgId +&' for update&);
&&&&&&&&&&&&&&&& if (rs.next()) {
&&&&&&&&&&&&&&&&&&&&&& blob = (BLOB) rs.getBlob(1);
&&&&&&&&&&&&&&&&&&&&&& outputStream = blob.getBinaryOutputStream();
&&&&&&&&&&&&&&&&&&&&&& file = new File(&c:\\4.gif&);
&&&&&&&&&&&&&&&&&&&&&& inputStream = new FileInputStream(file);
&&&&&&&&&&&&&&&&&&&&&& byte[] b = new byte[blob.getBufferSize()];
&&&&&&&&&&&&&&&&&&&&&& int len = 0;
&&&&&&&&&&&&&&&&&&&&&& while ((len = inputStream.read(b)) != -1) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&& System.out.println(len);
&&&&&&&&&&&&&&&&&&&&&&&&&&&& outputStream.write(b, 0, len);
&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&& }
&&&&&&&&&& } catch (SQLException e) {
&&&&&&&&&&&&&&&& // TODO Auto-generated catch block
&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&& } catch (FileNotFoundException e) {
&&&&&&&&&&&&&&&& // TODO Auto-generated catch block
&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&& } catch (IOException e) {
&&&&&&&&&&&&&&&& // TODO Auto-generated catch block
&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&& } finally {
&&&&&&&&&&&&&&&& try {
&&&&&&&&&&&&&&&&&&&&&& inputStream.close();
&&&&&&&&&&&&&&&&&&&&&& outputStream.flush();
&&&&&&&&&&&&&&&&&&&&&& outputStream.close();
&&&&&&&&&&&&&&&&&&&&&& rs.close();
&&&&&&&&&&&&&&&&&&&&&& st.close();
&&&&&&&&&&&&&&&&&&&&&& mit();
&&&&&&&&&&&&&&&&&&&&&& conn.close();
&&&&&&&&&&&&&&&& } catch (IOException e) {
&&&&&&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block
&&&&&&&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&&&&&&& } catch (SQLException e) {
&&&&&&&&&&&&&&&&&&&&&& // TODO Auto-generated catch block
&&&&&&&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&&&&&&& }
&&&&&&&&&& }
操作完毕!
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'查看: 6769|回复: 6
怎样提取blob数据类型中的信息
论坛徽章:5
各位好,有没有办法把表中blob数据类型的信息提出来!
以下是我的一个blob类型的其中一条数据,
如果我想查找column name=&T6_3_1_1& 的值&水城分局&,查出来后导入另一个表中,怎么实现呢?blob类型存的好像是二进制的,如果直接用dbms_lob.substr()去取的话,出来的也不是字符的信息,而是一些看不到的东西,在网上查了很久也没有找到怎么实现,好像java可以实现,难道在后台就不能实现吗?怎么办呢?)
&?xml version=&1.0& encoding=&GB18030&?&
& & & & &rowset name=&epm/apcontract/AF_CONTRACT_LOW&&
& & & & & & & & &row num=&0&&
& & & & & & & & & & & & &column name=&CUST_ADDR& value=&钟山开发区恒裕楼4号302室&&&/column&
& & & & & & & & & & & & &column name=&ELEC_KIND& value=&正式&&&/column&
& & & & & & & & & & & & &column name=&TARIFF_CODE& value=&居民生活电价1kV以下&&&/column&
& & & & & & & & & & & & &column name=&CONTACT_CAPA& value=&8&&&/column&
& & & & & & & & & & & & &column name=&T6_3_1_1& value=&水城分局&&&/column&
& & & & & & & & & & & & &column name=&T6_3_1_2& value=&营业大厅&&&/column&
& & & & & & & & & & & & &column name=&T6_3_2_1& value=&农行、工行&&&/column&
& & & & & & & & & & & & &column name=&T6_3_2_2& value=&中行、建行&&&/column&
& & & & & & & & & & & & &column name=&T12_1& value=&&&&/column&
& & & & & & & & & & & & &column name=&T12_2& value=&&&&/column&
& & & & & & & & &/row&
& & & & &/rowset&
&/rowsets&
论坛徽章:434
试一下这个:
DBMS_LOB.CONVERTTOCLOB
论坛徽章:24
应该就是利用dbms_lob 这个包了
论坛徽章:24
今天我才发现原来还有个呢
好像也是ITpub旗下的。
论坛徽章:5
DBMS_LOB&&这个 包我 折腾了好久,貌似只能保存读取,没有太多的功能,,,
& & 你这个实现 用java IO读出文件,然后用 dom4j,jdom 之类的包很容易处理,效率也很高,,包括添加节点,删除节点怎么折腾都行,,
& && &后台还是存取吧,,,
论坛徽章:24
& && &&&file1& &
& && &&&ll& && &
& && &&&vb_loc2 blob := empty_blob();
& && &&&vr_raw2 raw(2000); ---临时raw
& && &&&loopct&&
& && &&&vi_
& && &begin
& && &&&file1 := bfilename('FILEDIR', iv_filename);
& && &&&ll& & := dbms_lob.getlength(file1);
& && &&&dbms_output.put_line(ll);
& && &&&select nvl(max(id), 0) into ii_
& && &&&ii_temp := ii_temp + 1;
& && &&&execute immediate 'insert into rt(id,name,ib) values(:1,:2, empty_blob())'
& && && & using ii_temp, iv_
& && &&&select ib into vb_loc2 from rt where id = ii_
& && &&&dbms_lob.open(file1, dbms_lob.lob_readonly);
& && &&&loopct := (ll - 1) / 2000 + 1;& && &
& && &&&for h in 1 .. loopct loop
& && && & dbms_lob.read(file1, amount, offset, vr_raw2);& && && &
& && && & dbms_lob.write(vb_loc2, amount, offset, vr_raw2);
& && && & offset := amount * h + 1;
& && &&&update rt set ib = vb_loc2 where id = ii_
这个是我写的一个读取文件到blob,再存到数据库中的用法,你可以参考一下
论坛徽章:24
select ib into vb_loc2 from rt where id = ii_
& && &&&dbms_lob.open(file1, dbms_lob.lob_readonly);
& && &&&loopct := (ll - 1) / 2000 + 1;& && &
& && &&&for h in 1 .. loopct loop
& && && & dbms_lob.read(file1, amount, offset, vr_raw2);& && && &
& && && & dbms_lob.write(vb_loc2, amount, offset, vr_raw2);
& && && & offset := amount * h + 1;
& && &&&update rt set ib = vb_loc2 where id = ii_
应该这一段就够了
itpub.net All Right Reserved. 北京皓辰网域网络信息技术有限公司版权所有    
 北京市公安局海淀分局网监中心备案编号: 广播电视节目制作经营许可证:编号(京)字第1149号在数据窗口中利用OLE Database Blob显示图片遇到的问题,神呀,救救我吧!我完全按照PB的说明书和本论坛上各位大哥的帖子来设计OLE & Database & Blob,但是在点数据窗口上的Retrieve按钮来显示时,总是出现
Select & error: & SQLSTATE=37000
[Sybase][ODBC & Driver][Adaptive & Server & Anywhere]Syntax & error & or & access & violation: & Syntax & error & near &
'(end & of & line) ' & on & line1
在Preview窗口中,双击OLE控件可以打开Windows画板,编辑后保存到数据库时,出现以下错误
QLSTATE & = & 37000
[Sybase][ODBC & Driver][Adaptive & Server & Anywhere]Syntax & error & or & access & violation: & Syntax & error & near &
'(end & of & line) ' & on & line & 1
No & changes & made & to & database.
UPDATEBLOB &
& FROM & dtu & WHERE & dm & = &
(很奇怪我明明写了检索条件,为什么只有“Where & dm= & ”呢?)
现在在数据窗口画板中既不能显示图片,也不能保存图片,实在不明白到底错在哪。
回答1:你的key clause 没有定义 可以定义为:dm=:dm,在数据窗口中选种你的tablebolb在属性里有definition标签,
peipei6_29
回答2:不需要双引号……
peipeilong

我要回帖

更多关于 将照片存为blob 的文章

 

随机推荐