在做整合之前先将ueditor源码放入项目同时了解一下ueditor的工作机制。
js报错是因为IDE工具自己的验证导致的,请忽略。。。
从ueditor的源码来看呢,入口在jsp下的controller.jsp
由本人亲自debug的情况来看,在第一次进入页面的时候会进入controller.jsp,主要是加载config.json中的配置内容;再次进入controller.jsp是在点击【上传图片】,当然如果将图片复制到富文本框中也是会触发该controller滴!
ActionEnter的整个调用过程如下图:
接下来重点来了,首先创建UeditorUploadImgServlet
public class UeditorUploadImgServlet extends HttpServlet {
Logger logger = LogManager.getLogger(getClass());
private static final long serialVersionUID = 5522372203700422672L;
private String configJsonPath = “”;
String rootPath = “”;
@Override
public void init() throws ServletException {
super.init();
configJsonPath = this.getServletContext().getRealPath("/")+"/static/UEditor/config.json";
rootPath = this.getServletConfig().getServletContext().getRealPath("/");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding( "utf-8" );
response.setHeader("Content-Type" , "text/html");
ActionEnter actionNew = new ActionEnter( request, rootPath, configJsonPath);
logger.info(JSONObject.toJSONString(actionNew));
response.getWriter().write(actionNew.exec());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding( "utf-8" );
response.setHeader("Content-Type" , "text/html");
try {
ActionEnter actionNew = new ActionEnter(request, rootPath, configJsonPath);
logger.info(JSONObject.toJSONString(actionNew));
String result = actionNew.exec();
logger.info(result);
response.getWriter().write(result);
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}
初始化的时候获取项目根路径【rootPath】以及config.json资源文件的位置
doGet方法初始化页面的时候ueditor会进入,取到config.json内容,
doPost方法是在上传文件时触发的,进入post方法后首先是执行new ActionEnter(request, rootPath, configJsonPath);
我们来看下ActionEnter里边具体执行的内容:
public ActionEnter ( HttpServletRequest request, String rootPath, String configJsonPath) {
this.request = request;
this.rootPath = rootPath;
this.actionType = request.getParameter( “action” );
this.contextPath = request.getContextPath();
this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, configJsonPath);
}
这里我们可以看到主要是初始化一些变量。
从soPost方法我们知道接下来执行的是exec()方法;
我们一步一步往下走会发现最后走到了invoke()方法中的switch分支里边,请看下图(3图)
而这里最终调用的是Uploader()方法;
public class Uploader {
private HttpServletRequest request = null;
private Map<String, Object> conf = null;
private String rootPath = null;
public Uploader(HttpServletRequest request, Map<String, Object> conf, String rootPath) {
this.request = request;
this.conf = conf;
this.rootPath = rootPath;
}
public final State doExec() {
String filedName = (String) this.conf.get("fieldName");
State state = null;
if ("true".equals(this.conf.get("isBase64"))) {
state = Base64Uploader.save(this.request.getParameter(filedName),
this.conf);
} else {
state = BinaryUploader.save(this.request, this.conf, this.rootPath);
}
return state;
}
}
由于我这里不是【isBase64】所以执行的else中的内容,由此我们又到了BinaryUploader的save()方法
关键点来了,
public class BinaryUploader {
private static Logger logger = LogManager.getLogger(BinaryUploader.class);
public static final State save(HttpServletRequest request, Map<String, Object> conf, String rootPath) {
FileItemStream fileStream = null;
boolean isAjaxUpload = request.getHeader("X_Requested_With") != null;
if (!ServletFileUpload.isMultipartContent(request)) {
return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
}
ServletFileUpload upload = new ServletFileUpload(
new DiskFileItemFactory());
if (isAjaxUpload) {
upload.setHeaderEncoding("UTF-8");
}
try {
FileItemIterator iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
fileStream = iterator.next();
if (!fileStream.isFormField())
break;
fileStream = null;
}
if (fileStream == null) {
return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
}
String savePath = (String) conf.get("savePath");// 保存路径【imagePathFormat】
String originFileName = fileStream.getName(); // 图片流
String suffix = FileType.getSuffixByFilename(originFileName);// 取到后缀名
originFileName = originFileName.substring(0,
originFileName.length() - suffix.length());
savePath = savePath + suffix;
long maxSize = ((Long) conf.get("maxSize")).longValue();
if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
}
savePath = PathFormat.parse(savePath, originFileName);// 保存路径真实生成的路径
String physicalPath = (String) conf.get("rootPath") + savePath;
InputStream is = fileStream.openStream();
// State storageState = StorageManager.saveFileByInputStream(is,
// physicalPath, maxSize); //此行注释掉
State storageState = null;
/**
* 上传到阿里云OSS by lichenyi
*
*/
// *******************开始***********************
String fileName = new StringBuffer().append(new Date().getTime()).append(fileStream.getName().substring(fileStream.getName().indexOf("."))).toString();
try {
// 创建上传Object的Metadata
//创建文件
UploadOSSUtil.createTempFile(rootPath+fileName, is);
//上传到OSS
UploadOSSUtil.uploadImgAliyun(new File(rootPath+fileName), fileName);
//删除文件
UploadOSSUtil.removeTempFile(rootPath+fileName);
storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize);
//storageState.putInfo("state", "SUCCESS");// UEDITOR的规则:不为SUCCESS则显示state的内容
// 注意:下面的url是返回到前端访问文件的路径,请自行修改
String host = "http://" + ApiUrl.bucket + "." + ApiUrl.endpoint;
storageState.putInfo("url", host + "/"+ ApiUrl.myPath +"/" + fileName);
storageState.putInfo("title", fileName);
storageState.putInfo("original", fileName);
} catch (Exception e) {
// TODO: handle exception
logger.error(e.getMessage());
storageState.putInfo("state", "文件上传失败!");
storageState.putInfo("url", "");
storageState.putInfo("title", "");
storageState.putInfo("original", "");
logger.error("文件 " + fileName + " 上传失败!");
}
// ********************结束**********************
is.close();
if (storageState.isSuccess()) {
//storageState.putInfo("url", PathFormat.format(savePath));
storageState.putInfo("type", suffix);
storageState.putInfo("original", originFileName + suffix);
}
return storageState;
} catch (FileUploadException e) {
return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
} catch (IOException e) {
}
return new BaseState(false, AppInfo.IO_ERROR);
}
private static boolean validType(String type, String[] allowTypes) {
List<String> list = Arrays.asList(allowTypes);
return list.contains(type);
}
public static final String getContentType(String fileName) {
String fileExtension = fileName.substring(fileName.lastIndexOf("."));
if ("bmp".equalsIgnoreCase(fileExtension))
return "image/bmp";
if ("gif".equalsIgnoreCase(fileExtension))
return "image/gif";
if ("jpeg".equalsIgnoreCase(fileExtension)
|| "jpg".equalsIgnoreCase(fileExtension)
|| "png".equalsIgnoreCase(fileExtension))
return "image/jpeg";
if ("html".equalsIgnoreCase(fileExtension))
return "text/html";
if ("txt".equalsIgnoreCase(fileExtension))
return "text/plain";
if ("vsd".equalsIgnoreCase(fileExtension))
return "application/vnd.visio";
if ("ppt".equalsIgnoreCase(fileExtension)
|| "pptx".equalsIgnoreCase(fileExtension))
return "application/vnd.ms-powerpoint";
if ("doc".equalsIgnoreCase(fileExtension)
|| "docx".equalsIgnoreCase(fileExtension))
return "application/msword";
if ("xml".equalsIgnoreCase(fileExtension))
return "text/xml";
return "text/html";
}
}
看到这里你们可能会有疑问,为什么拿到了输入流,还要再创建临时文件,通过OSS上传呢?
其实呢,通过输入流上传我也试了,可能因为没有找对方法吧,最终还是失败了,(叹气。。。)
下面是UploadOSSUtil类
public class UploadOSSUtil {
private static Logger logger = LogManager.getLogger(UploadOSSUtil.class);
public UploadOSSUtil() {
}
public static void uploadImgAliyun(File file, String fileName) throws FileNotFoundException {
String endpoint = ApiUrl.endpoint;
String accessId = ApiUrl.accessId;
String accessKey = ApiUrl.accessKey;
String bucket = ApiUrl.bucket;
String dir = ApiUrl.myPath+"/";
OSSClient client = new OSSClient("http://"+endpoint, accessId, accessKey);
client.putObject(bucket, dir + fileName, file);
client.shutdown();
}
public static void createTempFile(String path, InputStream inputStream){
try {
DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(path));
int byteCount = 0;
//1M逐个读取
byte[] bytes = new byte[1024*1024];
while ((byteCount = inputStream.read(bytes)) != -1){
outputStream.write(bytes, 0, byteCount);
}
inputStream.close();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
logger.error(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage());
}
}
public static void removeTempFile(String path){
File file = new File(path);
file.delete();
}
}
按照以上步骤整合之后,发现返回值是OK的,但是富文本框中就是不现实图片, 最后没办法,用map重新写了一次,细心的童鞋会发现,图3最后一行代码是注释掉的,一下代码紧接该该处
代码:https://github.com/lichenyigit/java.ueditorOSS.demo
至此全部整合完毕,有什么问题请留言,感谢不吝赐教
另附上springboot 和 ueditor整合的demo:
https://github.com/lichenyigit/java.springBootUEditorOSS.demo.git