开发环境:struts2+ spring + hibernate
数据库:oracle
需求:在HTML编辑器中输入文章,传入后台,文章中所有图片路径,转换成base64编码,将文章存入数据库中的CLOB字段。
知识点:HTML编辑器,html解析,base64编码,String到CLOB类型转换
一般情况下,数据库只需要保存图片的路径就可以了,图片文件放在项目文件夹中,显示时只需加载图片路径即可。但是时下信息共享的渠道太多了 ,当IOS,android,微信公众号都操作同一个数据库的时候,上述方案是无法加载到图片的。因此我想到一个办法就是上传图片后,将路径替换为base64编码,存入数据库即可。
我使用的编辑器是kindeditor,演示内容:
备注:kindeditor上传图片的功能会和struts2会有冲突,因为struts2过滤jsp时会改变request类型,解决方法链接http://blog.csdn.net/kunkun378263/article/details/23274369
文章内容传到后台后,调用HTML解析类的编码方法 ,并用hibernate的createClob方法将String 转成CLOB,添加到数据库。
Action方法:
public String add(){
String content = request.getParameter("content");
Clob clob =Hibernate.createClob(HtmlJsoup.html_ImgToBase64(content));
article.setContent(clob);
service.add(article);
return SUCCESS;
}
我使用的HTML解析器是jsoup,类名和方法名都是和javaScript相类似的,对于会jquery的同学简直是福音,非常好理解非常好用,下面是我自己写的HTML解析类的代码,在转码前还会调用一个使用了正则表达式的方法用于检测路径是否为有效路径。
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.struts2.ServletActionContext;
import org.jsoup.Jsoup;
import org.jsoup.nodes.*;
import org.jsoup.select.Elements;
public class HtmlJsoup {
/**
* 检测图片路径是否为真实有效的路径方法
* @param src
* @return
*/
public static boolean checkImage(String src){
//使用正则表达式,排除img标签src属性值已经是base64编码的情况
Pattern pattern = Pattern.compile("^data:image/(png|gif|jpg|jpeg|bmp|tif|psd|ICO);base64,.*");
Matcher matcher = pattern.matcher(src);
if(matcher.matches())
return false;
//排除src路径并非图片格式的情况
pattern=Pattern.compile("^.*[.](png|gif|jpg|jpeg|bmp|tif|psd|ICO)$");
matcher = pattern.matcher(src);
if(!matcher.matches())
return false;
//排除图片路径不存在的情况
String path = ServletActionContext.getServletContext().getRealPath(src.substring(5, src.length()));
File file = new File(path);
if(!file.exists())
return false;
return true;
}
public static String html_ImgToBase64(String html){
Document doc = Jsoup.parse(html, "utf-8");
Elements imgs = doc.getElementsByTag("img");
for(Element img :imgs){
String src = img.attr("src");
if(!checkImage(src))
continue;
//将有效的路径传入base64编码的方法
img.attr("src",ImageBase64.imageToBase64Head(src));
}
//返回base64编码后的html文档
return doc.getElementsByTag("body").html();
}
}
最后是图片转base64的编码类代码,记得要带上头文件,不然显示时无法识别。
import java.io.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.struts2.ServletActionContext;
public class ImageBase64 {
/**
* 将图片转换成Base64编码 ,带头文件
* @param imgFile 待处理图片
* @return
*/
public static String imageToBase64Head(String imgFile){
//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
String type = imgFile.substring(imgFile.length()-3,imgFile.length());
//为编码添加头文件字符串
String head = "data:image/"+type+";base64,";
return head + imageToBase64(imgFile);
}
/**
* 将图片转换成Base64编码
* @param imgFile 待处理图片
* @return
*/
public static String imageToBase64(String imgFile){
//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
//拿到上传图片后,图片所在的项目中真实路径
String path = ServletActionContext.getServletContext().getRealPath(imgFile.substring(5, imgFile.length()));
InputStream in = null;
byte[] data = null;
try
{
//读取图片字节数组
in = new FileInputStream(path);
data = new byte[in.available()];
in.read(data);
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return new String(Base64.encodeBase64(data));
}
}
存入到CLOB字段后,就是这样了
最后是一些使用到的jar包