不知道大家有没有这样一个需求:发布一篇文章,文章内容中可能涉及到图片,那么显示文章时候,如何展示文章如发布一样(包括图片),csdn 的发布文章就是一个很好的例子,虽然我不知道csdn是如何实现的,但我自己的实现方法主要有两种:
1.在富文本编辑器中上传图片,以IO流方式存储到文件服务器,上传成功后,返回图片的http地址(回显)
2.在富文本编辑器中上传图片,将图片以base64方式存储到数据表中
本文章讲的是第二种方式(base64):
demo样例(demo下载):
注:
富文本编辑器:wangEditor2
数据库:SQL Server
开发环境:jdk1.8.0 、java语言
步骤:
1.首先,创建示例数据表如下图(demo完成后自行上传404图片):
2.制作富文本编辑器UI页面index.jsp
3.富文本编辑器处理上传js:
$(function() {
var path = $("#path").val();
var editor = new wangEditor('div1');
// 自定义菜单
editor.config.menus = [
'lineheight',
'undo',
'bold',
'italic',
'underline',
'strikethrough',
'fontfamily',
'fontsize',
'forecolor',
'bgcolor',
'table',
'img'
];
/*
* 默认菜单
* [
'source',
'|',
'bold',
'underline',
'italic',
'strikethrough',
'eraser',
'forecolor',
'bgcolor',
'|',
'quote',
'fontfamily',
'fontsize',
'head',
'unorderlist',
'orderlist',
'alignleft',
'aligncenter',
'alignright',
'|',
'link',
'unlink',
'table',
'emotion',
'|',
'img',
'video',
'location',
'insertcode',
'|',
'undo',
'redo',
'fullscreen'
];
* */
// 字体
editor.config.familys = [
'宋体','仿宋GB2312','华文仿宋', '黑体', '楷体', '微软雅黑',
'Arial', 'Verdana', 'Georgia'
];
// 字号
editor.config.fontsizes = {
// 格式:'value': 'title'
1: '10',
2: '10.5',
3: '11',
4: '11.5',
5: '12',
6: '12.5',
7: '13',
8: '13.5',
9: '14',
10: '14.5',
11: '15',
12: '15.5',
13: '16'
};
// 上传图片
editor.config.uploadImgUrl = path+"/upload/uploadManager.jsp?method=post";
// 关闭粘贴内容中的样式
//editor.customConfig.pasteFilterStyle = false
// 忽略粘贴内容中的图片
//editor.customConfig.pasteIgnoreImg = true
// 使用 base64 保存图片
//editor.customConfig.uploadImgShowBase64 = true
// 若需传参,请在此配置参数
editor.config.uploadParams = {
/* token1: 'abcde',
token2: '12345'*/
};
editor.config.uploadHeaders = {
// 'Accept' : 'text/x-json'
}
// 配置统一名字,方便后台获取
editor.config.uploadImgFileName = 'myFileName';
// 隐藏网络图片
editor.config.hideLinkImg = true;
// 将图片大小限制为 3M
//editor.customConfig.uploadImgMaxSize = 3 * 1024 * 1024;
// 自定义上传图片事件
editor.config.uploadImgFns.onload = function (resultText, xhr) {
// resultText 服务器端返回的text
// xhr 是 xmlHttpRequest 对象,IE8、9中不支持
var data = JSON.parse(resultText.trim());
//srcList.add(basePath+"/upload/uploadManager.jsp?method=get&FID="+FID);
var FIDs = data.FIDs;
for(var i in FIDs){
var fid = FIDs[i];
var src = path+"/upload/uploadManager.jsp?method=get&FID="+fid;
// 上传图片时,已经将图片的名字存在 editor.uploadImgOriginalName
var originalName = editor.uploadImgOriginalName || '';
// 如果 resultText 是图片的url地址,可以这样插入图片:
editor.command(null, 'insertHtml', '');
// 如果不想要 img 的 max-width 样式,也可以这样插入:
// editor.command(null, 'InsertImage', resultText);
}
};
// 自定义timeout事件
editor.config.uploadImgFns.ontimeout = function (xhr) {
// xhr 是 xmlHttpRequest 对象,IE8、9中不支持
alert('上传超时');
};
// 自定义error事件
editor.config.uploadImgFns.onerror = function (xhr) {
// xhr 是 xmlHttpRequest 对象,IE8、9中不支持
alert('上传错误');
};
// 插入代码时的默认语言
// editor.config.codeDefaultLang = 'html'
// 只粘贴纯文本
// editor.config.pasteText = true;
// 跨域上传
// editor.config.uploadImgUrl = 'http://localhost:8012/upload';
// 第三方上传
// editor.config.customUpload = true;
// 普通菜单配置
// editor.config.menus = [
// 'img',
// 'insertcode',
// 'eraser',
// 'fullscreen'
// ];
// 只排除某几个菜单(兼容IE低版本,不支持ES5的浏览器),支持ES5的浏览器可直接用 [].map 方法
// editor.config.menus = $.map(wangEditor.config.menus, function(item, key) {
// if (item === 'insertcode') {
// return null;
// }
// if (item === 'fullscreen') {
// return null;
// }
// return item;
// });
// onchange 事件
editor.onchange = function () {
// var text = this.$txt.html().replace("a","span").replace("href","h");
//this.$txt.html(text);
console.log(this.$txt.html());
};
// 取消过滤js
// editor.config.jsFilter = false;
// 取消粘贴过来
// editor.config.pasteFilter = false;
// 设置 z-index
// editor.config.zindex = 20000;
// 语言
// editor.config.lang = wangEditor.langs['en'];
// 自定义菜单UI
// editor.UI.menus.bold = {
// normal: '',
// selected: '.selected'
// };
// editor.UI.menus.italic = {
// normal: '',
// selected: ''
// };
editor.create();
})
4.后台将图片保存至数据库:
package com.demo.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.jasper.tagplugins.jstl.core.Out;
import org.json.JSONObject;
import com.demo.utils.DBUtils;
import com.google.gson.Gson;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class UploadImages {
public static void main(String[] args) {
new Gson();
}
public static List uploadImages(HttpServletRequest request) throws IOException {
Connection conn = null;
String basePath = request.getContextPath();
List FIDs = new ArrayList();
BASE64Encoder encoder = new BASE64Encoder();
/** 上传文件处理内容 **/
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
sfu.setHeaderEncoding("UTF-8"); // 处理中文问题
sfu.setSizeMax(10 * 1024 * 1024); // 限制文件大小
try {
conn = DBUtils.getConnection();
if (conn != null) {
StringBuffer sql = new StringBuffer("");
List fileItems = sfu.parseRequest(request); // decode request
for (FileItem fi : fileItems) {
String FID = getUUID();
if(!FID.equals("")) {
String imgName = fi.getName();
String imgByte = encoder.encode(fi.get());
sql.append(" INSERT INTO Base64Images(FID,imageName,imageObj,IsDelete) ");
sql.append(" VALUES ");
sql.append(" ('"+FID+"','"+imgName+"','"+imgByte+"',0) ");
Statement stm = conn.createStatement();
int i = stm.executeUpdate(sql.toString());
stm.close();
if(i > 0) {
FIDs.add(FID);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
DBUtils.release(conn);
}
/**********************/
return FIDs;
}
public static String getUUID() {
String FID = "";
Connection conn = null;
try {
conn = DBUtils.getConnection();
if (conn != null) {
String sql0 = " SELECT NEWID() AS UUID ";
Statement stm0 = conn.createStatement();
ResultSet rs0 = stm0.executeQuery(sql0);
while(rs0.next()) {
FID = rs0.getString("UUID");
}
rs0.close();
stm0.close();
}
}catch(Exception e) {
e.printStackTrace();
}finally {
DBUtils.release(conn);
}
return FID;
}
public static void outImage(String FID,HttpServletResponse response) {
byte[] bytes = getImage(FID);
bytes = (bytes==null)?new byte[0]:bytes;
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
ServletOutputStream ot = null;
try {
ot = response.getOutputStream();
ot.write(bytes);
ot.flush();
ot.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] getImage(String FID) {
if (FID == null || FID.trim().equals("")) {
return null;
}
byte[] bytes = null;
Connection conn = null;
BASE64Decoder decoder = new BASE64Decoder();
try {
conn = DBUtils.getConnection();
if (conn != null) {
boolean imgExist = false;
String sql = " SELECT FID,imageObj FROM Base64Images WHERE FID = '" + FID + "' ";
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery(sql);
byte[] imgByte = null;
while (rs.next()) {
imgByte = (rs.getBytes("imageObj")==null)?null:rs.getBytes("imageObj");
}
//若根据FID在数据库找不到图片,则返回404.jpg
if(imgByte == null) {
String sql2 = " SELECT FID,imageObj FROM Base64Images WHERE FID = '4F40DD81-F262-4FB8-9463-7F3A29F2D8D1' ";
Statement stm2 = conn.createStatement();
ResultSet rs2 = stm2.executeQuery(sql2);
while (rs2.next()) {
imgByte = (rs2.getBytes("imageObj")==null)?null:rs2.getBytes("imageObj");
}
DBUtils.release(stm2, rs2);
}
DBUtils.release(stm, rs);
if(imgByte != null) {
imgExist = true;
String imgByteStr = new String(imgByte, "UTF-8");
bytes = decoder.decodeBuffer(imgByteStr);
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] < 0) {
bytes[i] += 256;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
DBUtils.release(conn);
}
return bytes;
}
}
5.图片回显: