如何读取及展示数据库中BLOB类型的图片
【前言】最近在做某一需求时,需要从Oracle数据库读取图片。本以为数据库存储的会是一个简单的url,前台可以直接展示,结果却发现是BLOB二进制类型,于是乎,百度/Google了关键字“二进制图片读取及展示”,发现有很多“抄来抄去”的文章或博客,但是文章的质量都很低,而且结构比较混乱,看完之后仍然是“不明所以”。
最后,花了近2个小时,耐心研究了一下,终于成功。于是总结如下,供大家参考,也作为自己积累备份所用!
【核心点】
1.在PO类中用byte[]类型直接接受BLOB类型; 2.将二进制转为Base64格式字符串(不要用sun.misc.BASE64Encoder类); 3.前台html页面通过<img src="data:image/png;base64,{图片字段}"/>标签展示。 |
1.需求概述
①从Oracle数据库的表中读取BLOB类型图片;
②在前端页面将图片展示出来。
2.创建PO类,在PO类中用byte[]类型直接接受BLOB类型
package com.netease.numen.plus.netease.model; import java.io.Serializable; /** * 读取二进制blob类型图片 * <p>Title: PhotoBytes</p> * @author Liyan * @date 2017年3月6日 下午5:02:22 */ public class PhotoBytes implements Serializable { private static final long serialVersionUID = -8775612234303127935L; /**二进制图片*/ private byte[] photoBytes; public byte[] getPhotoBytes() { return photoBytes; } public void setPhotoBytes(byte[] photoBytes) { this.photoBytes = photoBytes; } }
3.编写Mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.**.netease.mapper.WorkCardMapper"> <resultMap id="photoBytes" type="com.**.netease.model.PhotoBytes"> <result column="PHOTO" property="photoBytes" /> </resultMap> <!-- 根据员工工号查询照片 --> <select id="getPhoto" resultMap="photoBytes"> SELECT PHOTO as photoBytes FROM EHRINBOUND.EHR_EMPLOYEE_PHOTO_V <where> <if test="jobNumber!=null"> AND EHR_EMPLOYEE_CODE = #{jobNumber} </if> </where> </select> </mapper>
4.编写Mapper.java文件
@Repository public interface WorkCardMapper { public PhotoBytes getPhoto(Map<String, Object> param) throws Exception; }
5.编写Service.java文件
public interface WorkCardService { public PhotoBytes getPhoto(final String jobNumber) throws Exception; }
6.编写ServiceImpl.java文件
@Service("workCardService") public class WorkCardServiceImpl implements WorkCardService{ @Inject WorkCardMapper mapper; @Override public PhotoBytes getPhoto(String jobNumber) throws Exception { Map<String, Object> param = new HashMap<String, Object>(0); param.put("jobNumber", jobNumber); } }
7.编写二进制流转Base64字符串的工具类
package com.netease.numen.plus.netease.util; import java.io.IOException; import org.apache.commons.codec.binary.Base64; public class Base64ImageUtil { /** * 二进制流转Base64字符串 * <p>Title: byteArr2String</p> * @author Liyan * @date 2017年3月6日 下午3:04:47 * @param data * @return String * @throws IOException */ public static String byteArr2String(byte[] byteArr) throws Exception { String stringBase64 = null; try { Base64 encoder = new Base64(); stringBase64 =(byteArr != null ? encoder.encodeToString(byteArr) : ""); } catch (Exception e) { throw new Exception("byteArr2String转换异常:"+e); } return stringBase64; } }
【引申:为什么不要使用sun.misc.BASE64Encoder类?】
很多人在使用Base64进行加密解密时,都是使用sun.misc包下的BASE64Encoder及BASE64Decoder。但是,可能会出现这样的状况:换了JDK后发现提示找不到该类! 网上有办法说重新配置jre就行了。但事实上不是这么简单的,这是要看配置的jre的类型是execution environment(执行环境),还是alternate jre(替代jre)。 这两种方法中,如果是第一种就不行,因为是执行环境,也就是不会含JDK的一些额外类,rt.jar中的很多包都会因为jre与jdk权限不同而导致被限定权限,其中就包含了sun包。 如果是第二种方法,即JDK替代jre,这就没问题,因为使用的是jdk的权限,所以不会报这类的错误。 但是,事实上,这两个方法都是sun公司的内部方法,并没有在java api中公开过,所以使用这些方法是不安全的,将来随时可能会从中去除,所以应该使用相应的替代对象及方法!【参考:http://fableking.iteye.com/blog/1426410】 |
8.编写Controller.java文件
以下为简写,主要步骤是将byte[]型转Base64的字符串,并返回给前端。实际还需要加上参数校验,异常处理,记录日志等逻辑。
package com.netease.numen.plus.netease.controller; @Controller @RequestMapping(value = "/workcard") public class WorkCardController { @Inject WorkCardService service; @RequestMapping(value = "/getWorkCardInfo" ) public String getWorkCardInfo(String jobNumber) { //根据员工工号,获取照片(byte[]类型) PhotoBytes photoBytes = service.getPhoto(jobNumber); byte[] photoBytes2 = photoBytes.getPhotoBytes(); //将二进制转为Base64格式字符串 String photo64 = Base64ImageUtil.byteArr2String(photoBytes2); result = new ResultInf(200, "获取照片信息成功", photo64); SpringMvcUtil.renderJson(response, result); return null; } }
9.前台html页面展示
<img src="data:image/png;base64,{photo}"/>