UEditor之基于Java图片上传前后端源码研究

2024-05-10 07:07:53

那么开始吧!

这是我的项目目录

这里写图片描述

1.从访问路径http://localhost:8081/Test/_examples/simpleDemo.html,我们主要是要看看,富文本框被加载出来之前,会调用哪些代码,

不卖关子,很明显,会调用后端的controller.jsp代码,因为我们已经在ueditor.config配置了:

, serverUrl: URL + "jsp/controller.js

看看controller.jsp代码,上一篇文章我们已经讲了,要把这些代码看作是后端代码,很重要很重要的:

<%@ page language="java" contentType="text/html; charset=UTF-8"import="com.baidu.ueditor.ActionEnter"
pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%request.setCharacterEncoding( "utf-8" );response.setHeader("Content-Type" , "text/html");/** 项目根路径 **/String rootPath = application.getRealPath( "/" );/** 调用后端的ActionEnter类,并执行exec方法 **/out.write( new ActionEnter( request, rootPath ).exec() );%>

我们就到ActionEnter.java看看吧,这个类就是前端调用后端的唯一入口,也只有这个入口了,记住第一章有讲了,要把源码复制到src下,进行调试哦!不知道先看第一章吧!!!!!

package com.baidu.ueditor;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import com.baidu.ueditor.define.ActionMap;
import com.baidu.ueditor.define.AppInfo;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.State;
import com.baidu.ueditor.hunter.FileManager;
import com.baidu.ueditor.hunter.ImageHunter;
import com.baidu.ueditor.upload.Uploader;public class ActionEnter {private HttpServletRequest request = null;private String rootPath = null;
private String contextPath = null;private String actionType = null;private ConfigManager configManager = null;
/** action统一入口 **/
public ActionEnter ( HttpServletRequest request, String rootPath ) {this.request = request;/** rootPath = /Test/ **/this.rootPath = rootPath;/** actionType = config **/this.actionType = request.getParameter( "action" );/** contextPath = /Test **/this.contextPath = request.getContextPath();/** 调用ConfigManager **/this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() );}

2.ConfigManager类主要用来读取后端的配置文件,就是config.json这个文件,事实上这个文件应该放在后端的。

* 配置管理器 * @author hancong03@baidu.com**/
public final class ConfigManager {private final String rootPath;
private final String originalPath;
private final String contextPath;
/** 存放备注文件 **/
private static final String configFileName = "config.json";
private String parentPath = null;
private JSONObject jsonConfig = null;
// 涂鸦上传filename定义
private final static String SCRAWL_FILE_NAME = "scrawl";
// 远程图片抓取filename定义
private final static String REMOTE_FILE_NAME = "remote";/** 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件*/
private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException {rootPath = rootPath.replace( "\\", "/" );//下面的rootPath就是我的根路径// rootPath=D:/workspace_de_client/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Test/this.rootPath = rootPath;this.contextPath = contextPath;//请求路径 url = /Test/jsp/controller.jspif ( contextPath.length() > 0 ) {// D:/workspace_de_client/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Test//jsp/controller.jspthis.originalPath = this.rootPath + uri.substring( contextPath.length() );} else {this.originalPath = this.rootPath + uri;}/** 调用当前类的初始化环境方法 initEnv **/this.initEnv();}//上面的方法无法就是获得controller.jsp这个类所在的真实目录而已//下面看看initEnv()这个方法private void initEnv () throws FileNotFoundException, IOException {/**  **/File file = new File( this.originalPath );if ( !file.isAbsolute() ) {file = new File( file.getAbsolutePath() );}/** 获得文件的父路径,也就是  ..../jsp **/this.parentPath = file.getParent();/** 读取配置文件,这个方法比较重要,往下看 **/String configContent = this.readFile( this.getConfigPath() );try{/** 把返回的的json字符串扔进JsonObject对象中 **/JSONObject jsonConfig = new JSONObject( configContent );this.jsonConfig = jsonConfig;} catch ( Exception e ) {this.jsonConfig = null;}}/** 获得配置路径,记住config.json是和controller.jsp放在同一个目录下的,很坑有木有 **/
private String getConfigPath () {/** 拼凑config.json的真实路径 **/return this.parentPath + File.separator + ConfigManager.configFileName;
}private String[] getArray ( String key ) {JSONArray jsonArray = this.jsonConfig.getJSONArray( key );String[] result = new String[ jsonArray.length() ];for ( int i = 0, len = jsonArray.length(); i < len; i++ ) {result[i] = jsonArray.getString( i );}return result;}
/** 获得配置文件的内容,变成字符串返回 **/
private String readFile ( String path ) throws IOException {StringBuilder builder = new StringBuilder();try {InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" );BufferedReader bfReader = new BufferedReader( reader );String tmpContent = null;while ( ( tmpContent = bfReader.readLine() ) != null ) {builder.append( tmpContent );}bfReader.close();} catch ( UnsupportedEncodingException e ) {// 忽略}//过滤输入字符串, 剔除多行注释以及替换掉反斜杠return this.filter( builder.toString() );}// 过滤输入字符串, 剔除多行注释以及替换掉反斜杠
private String filter ( String input ) {return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" );}

从上面的方法中,读取配置文件的所有后端代码就都执行完了吧!!!!很简单吧!!!!

3.后端代码执行完之后,富文本框就初始化出来了,很有成就感吧!!
如图:

这里写图片描述

我们点击上传图片的按钮,选择一张图片上传,好,接下来就看看前端是如何调用,以及后端是如何保存文件的吧!!

我们看simpleupload.js这个文件,它是实现单文本上传的主要前段代码,很重要的

我们从53行开始看也就是:domUtils.on(input, ‘change’, function() 找不到可以Ctrl +F,相信这点技能还是有的吧,否则就不适合这个行业了 !!!!

这里我要说明下,ueditor读取配置文件的顺序,是:

后端返回json配置文件 --> 用户自定义的配置文件 --> ueditor.config

好了,开始来调用后端的代码了,一样是调用ActionEnter.java这个类
前端的请求路径是

"http://localhost:8081/Test/jsp/controller.jsp?action=uploadp_w_picpath" /*** 处理不同类型的回调函数* @return*/
public String invoke() {//自己添加上去的Map<string, integer=""> mapping = ActionMap.mapping;if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) {return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString();}if ( this.configManager == null || !this.configManager.valid() ) {return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString();}State state = null;// 获得actionType类型码 ActionMap这个类我就不介绍了,自己可以看看,主要是封装的一些常量int actionCode = ActionMap.getType( this.actionType );Map<string, object=""> conf = null;switch ( actionCode ) {//如果配置文件,执行下面的方法,这个就是我们开始讲的后端读取的配置文件执行的逻辑case ActionMap.CONFIG:return this.configManager.getAllConfig().toString();//这里是我们这次重点讲解的路径,图片上传,视频上传都执行这个路基   case ActionMap.UPLOAD_IMAGE:case ActionMap.UPLOAD_SCRAWL:case ActionMap.UPLOAD_VIDEO:case ActionMap.UPLOAD_FILE://发现没有,这里获得配置文件,看到这里,你应该先看getConfig这个方法,跟着思路走,不是是跟着调试代码走conf = this.configManager.getConfig( actionCode );//这里就是执行文件上传的方法了,看完上面代码才可以看这里呀,不要急state = new Uploader( request, conf ).doExec();break;case ActionMap.CATCH_IMAGE:conf = configManager.getConfig( actionCode );String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );state = new ImageHunter( conf ).capture( list );break;case ActionMap.LIST_IMAGE:case ActionMap.LIST_FILE:conf = configManager.getConfig( actionCode );int start = this.getStartIndex();state = new FileManager( conf ).listFile( start );break;}return state.toJSONString();}

看看configManager.getConfig这个类
//如何是获得后端的所有配置,调用这个方法

public JSONObject getAllConfig () {
return this.jsonConfig;}//获得部分的配置
public Map<string, object=""> getConfig ( int type ) {Map<string, object=""> conf = new HashMap<string, object="">();String savePath = null;switch ( type ) {case ActionMap.UPLOAD_FILE:conf.put( "isBase64", "false" );conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) );conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) );conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) );savePath = this.jsonConfig.getString( "filePathFormat" );break;//上传图片逻辑    case ActionMap.UPLOAD_IMAGE:conf.put( "isBase64", "false" );conf.put( "maxSize", this.jsonConfig.getLong( "p_w_picpathMaxSize" ) );conf.put( "allowFiles", this.getArray( "p_w_picpathAllowFiles" ) );//看看看,走在路上别瞎看,看这里很重要的//p_w_picpathFieldName 图片名称conf.put( "fieldName", this.jsonConfig.getString( "p_w_picpathFieldName" ) );//图片保存路径,有没有发现在config.json配置的p_w_picpathPathFormat返回前端变成savePathsavePath = this.jsonConfig.getString( "p_w_picpathPathFormat" );break;case ActionMap.UPLOAD_VIDEO:conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) );conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) );conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) );savePath = this.jsonConfig.getString( "videoPathFormat" );break;case ActionMap.UPLOAD_SCRAWL:conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME );conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) );conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) );conf.put( "isBase64", "true" );savePath = this.jsonConfig.getString( "scrawlPathFormat" );break;case ActionMap.CATCH_IMAGE:conf.put( "filename", ConfigManager.REMOTE_FILE_NAME );conf.put( "filter", this.getArray( "catcherLocalDomain" ) );conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) );conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) );conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" );savePath = this.jsonConfig.getString( "catcherPathFormat" );break;case ActionMap.LIST_IMAGE:conf.put( "allowFiles", this.getArray( "p_w_picpathManagerAllowFiles" ) );conf.put( "dir", this.jsonConfig.getString( "p_w_picpathManagerListPath" ) );conf.put( "count", this.jsonConfig.getInt( "p_w_picpathManagerListSize" ) );break;case ActionMap.LIST_FILE:conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) );conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) );conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) );break;}conf.put( "savePath", savePath );conf.put( "rootPath", this.rootPath );return conf;}

接下了这个类Uploader.java

package com.baidu.ueditor.upload;
import com.baidu.ueditor.define.State;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;public class Uploader {private HttpServletRequest request = null;private Map<string, object=""> conf = null;public Uploader(HttpServletRequest request, Map<string, object=""> conf) {this.request = request;this.conf = conf;}public final State doExec() {String filedName = (String) this.conf.get("fieldName");State state = null;//重点在这里if ("true".equals(this.conf.get("isBase64"))) {//重点看这里,好了,知道我们要干嘛了吧!!!看Base64Uploader类的代码state = Base64Uploader.save(this.request.getParameter(filedName),this.conf);} else {state = BinaryUploader.save(this.request, this.conf);}return state;}
}

接下来看这个类的方法:BaseUploader.java,这里的save方法就是把文件保存到硬盘上

package com.baidu.ueditor.upload;
import com.baidu.ueditor.PathFormat;
import com.baidu.ueditor.define.AppInfo;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.FileType;
import com.baidu.ueditor.define.State;import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;public class BinaryUploader {public static final State save(HttpServletRequest request,Map<string, object=""> conf) {FileItemStream fileStream = null;boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;if (!ServletFileUpload.isMultipartContent(request)) {return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);}//common-io包中类,用于文件上传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");//文件原始名称                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这个类很重要,是一个接口,它是返回到前端的数据State storageState = StorageManager.saveFileByInputStream(is,physicalPath, maxSize);  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);}
}

最后,我们再看一个类就是State这个类,它是一个接口,我们主要是看它的实现类BaseState
这个类很重要,很重要,很重要,重要事情说3遍:::

介绍下吧:

这个类主要是返回前端的数据,格式就是下面这个样子,格式一定要对,否则前端会出现问题

package com.baidu.ueditor.define;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;import com.baidu.ueditor.Encoder;public class BaseState implements State {//状态码private boolean state = false;private String info = null;//里面存保存好的文件路径和private Map<string, string=""> infoMap = new HashMap<string, string="">();public BaseState () {this.state = true;}public BaseState ( boolean state ) {this.setState( state );}public BaseState ( boolean state, String info ) {this.setState( state );this.info = info;}public BaseState ( boolean state, int infoCode ) {this.setState( state );this.info = AppInfo.getStateInfo( infoCode );}public boolean isSuccess () {return this.state;}public void setState ( boolean state ) {this.state = state;}public void setInfo ( String info ) {this.info = info;}public void setInfo ( int infoCode ) {this.info = AppInfo.getStateInfo( infoCode );}@Overridepublic String toJSONString() {return this.toString();}/** 这里很重要的,也很简单,它把infoMap手工拼凑成json字符串返回回去 **/public String toString () {String key = null;String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;StringBuilder builder = new StringBuilder();builder.append( "{\"state\": \"" + stateVal + "\"" );Iterator<string> iterator = this.infoMap.keySet().iterator();while ( iterator.hasNext() ) {key = iterator.next();builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" );}builder.append( "}" );   return Encoder.toUnicode( builder.toString() );}@Overridepublic void putInfo(String name, String val) {this.infoMap.put(name, val);}@Overridepublic void putInfo(String name, long val) {this.putInfo(name, val+"");}}

4.上面后端的代码已经调完了,接下来就是后端数据返回到前端

之前讲过,看前端的simpleupload.js

后端返回数据后会调用回调函数的callback()方法

function callback(){                try{var link, json, loader,body = (iframe.contentDocument || iframe.contentWindow.document).body,result = body.innerText || body.textContent || '';//这里result就是后端返回的数据json = (new Function("return " + result))();//p_w_picpathUrlPrefix这个很重要很重要很重要,如果没配置的话,图片可能显示不出来//link就是图片的路径link = me.options.p_w_picpathUrlPrefix + json.url;if(json.state == 'SUCCESS' && json.url) {loader = me.document.getElementById(loadingId);loader.setAttribute('src', link);loader.setAttribute('_src', link);loader.setAttribute('title', json.title || '');loader.setAttribute('alt', json.original || '');loader.removeAttribute('id');domUtils.removeClasses(loader, 'loadingclass');} else {showErrorLoader && showErrorLoader(json.state);}}catch(er){showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError'));}form.reset();domUtils.un(iframe, 'load', callback);}function showErrorLoader(title){if(loadingId) {var loader = me.document.getElementById(loadingId);loader && domUtils.remove(loader);me.fireEvent('showmessage', {'id': loadingId,'content': title,'type': 'error','timeout': 4000});}}

参考:http://blog.csdn.net/huangwenyi1010/article/details/51637439

转载于:https://blog.51cto.com/4925054/1919721

UEditor之基于Java图片上传前后端源码研究相关推荐

  1. Java做图片上传、文件上传、 批量上传、 Base64图片上传 。附上源码

    Java做文件上传.图片上传后台方法 利用Springboot快速搭建项目环境 项目源码已经上传到码云:https://gitee.com/jack_party/upload .喜欢的朋友可以支持一下 ...

  2. 使用百度UMeditor富文本编辑器,修改自定义图片上传,修改源码

    富文本编辑器,不多说了,这个大家应该都用到过,至于用到的什么版本,那就分很多种 CKEditor:很早以前叫FCK,那个时候也用过,现在改名了,比较流行的一个插件,国外很多公司在用 UEDITOR:百 ...

  3. java图片上传(mvc)

    最近有开始学起了java,好久没写文章了,好久没来博客园了.最近看了看博客园上次写的图片上传有很多人看,今天在一些篇关于java图片上传的.后台接收用的是mvc.不墨迹了,直接上图. 先看目录结构.i ...

  4. java图片上传保存至服务器并返回可下载的URL

    java图片上传保存至服务器并返回可下载的URL 1.需求来源 2.解决思路 3.开始干活(直接上代码) 4.总结 1.需求来源 上周要做一个功能,需求是: 微信小程序开发的程序会传一张图片到后台ja ...

  5. html之file标签 --- 图片上传前预览 -- FileReader

    记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...

  6. input文件框选择本地图片后页面预览图片并获取图片长宽以及大小 图片上传前预览

    前面有转过一篇通过HTML5来实现图片上传前预览 ,现在借助FileReader也实现了这个需求.并且同时还可以获得图片的长宽相素以及图片文件的大小.demo如下: <html> < ...

  7. JavaScript 实现图片上传前本地预览

    JavaScript 实现图片上传前本地预览 图片上传前预览,应该算是一个普遍的需求,很多时候可能选中的图片并不是想要的那张,所以需要上传前预览下. JS(浏览器中)是一门特殊的语言,它没有直接读写磁 ...

  8. Java 图片上传后为什么会自动旋转90度?

    问题: 用户反馈上传后的图片方向不对,起初怀疑是本身图片方向有问题,但是用windows图片查看器打开图片方向是"正常"显示的? 分析: windows默认的图片查看器已经帮我们自 ...

  9. java图片上传和加水印

    java图片上传和加水印 简介 大家在做项目开发的时候,经常会用到图片上传,有些牵扯到版权或者私密的图片需要进行添加上水印,小编在总结了前人的经验之后,总结了一份element ui+spring b ...

最新文章

  1. 年后跳槽BAT必看:10种数据结构、算法和编程课助你面试通关
  2. 翻遍用AI检测新冠的论文,一篇临床可用的也没有?!
  3. 物体三维识别论文介绍——基于霍夫投票
  4. leetcode算法题--二叉树的锯齿型层次遍历
  5. Python 学习散记
  6. Leetcode 102. Binary Tree Level Order Traversal(二叉树的层序遍历)
  7. 14.5.5 Creating a File-Per-Table Tablespace Outside the Data Directory
  8. 余数运算符在Java中用于Doubles
  9. php类实例化js,php中如何实例化一个类_后端开发
  10. Observer(观察者)模式
  11. CVPR 2021 论文大盘点-去雾去模糊篇
  12. 推荐工具 HBuilder
  13. MySql解除安全模式
  14. shell 值判断,大于0,等于0,小于0,大于等于0,小于等于0,不等于0
  15. vant适配移动端750设计稿
  16. 命令行工具下载b站视频
  17. html版贪吃蛇的项目计划书,自动贪吃蛇.html
  18. python ccf题解 201809-1 卖菜
  19. 《人力资源管理》在线作业
  20. mysql怎么创建库和创建表?

热门文章

  1. 从零开始搭建一个测试技术练习平台
  2. Opencv 中 Mat中元素的值读取方法总结
  3. flask框架_Flask框架的入门:Hello world
  4. gx works2 存储器空间或桌面堆栈不足_2020福清市gx螺旋输送机价格厂家发货-衡泰...
  5. linux中nfs存储权限,NFS权限管理 - 麦苗的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. python化学公式_(CSP)201912-3化学方程式-python实现
  7. java并行调度_java并行调度框架封装及示例
  8. 29留数及其应用(五)
  9. Matlab绘图设置总结
  10. java中怎么把两个JTextfield中的数字相加的值放到另一个JTextfield?_如何将jtextfield中的值解析为整数并对其执行一些数学操作?...