300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > UEditor之基于Java图片上传前后端源码研究

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

时间:2023-11-10 17:38:09

相关推荐

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

那么开始吧!

这是我的项目目录

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

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

,serverUrl:URL+"jsp/controller.js

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

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

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

packagecom.baidu.ueditor;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;importcom.baidu.ueditor.define.ActionMap;importcom.baidu.ueditor.define.AppInfo;importcom.baidu.ueditor.define.BaseState;importcom.baidu.ueditor.define.State;importcom.baidu.ueditor.hunter.FileManager;importcom.baidu.ueditor.hunter.ImageHunter;importcom.baidu.ueditor.upload.Uploader;publicclassActionEnter{privateHttpServletRequestrequest=null;privateStringrootPath=null;privateStringcontextPath=null;privateStringactionType=null;privateConfigManagerconfigManager=null;/**action统一入口**/publicActionEnter(HttpServletRequestrequest,StringrootPath){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这个文件,事实上这个文件应该放在后端的。

*配置管理器*@authorhancong03@**/publicfinalclassConfigManager{privatefinalStringrootPath;privatefinalStringoriginalPath;privatefinalStringcontextPath;/**存放备注文件**/privatestaticfinalStringconfigFileName="config.json";privateStringparentPath=null;privateJSONObjectjsonConfig=null;//涂鸦上传filename定义privatefinalstaticStringSCRAWL_FILE_NAME="scrawl";//远程图片抓取filename定义privatefinalstaticStringREMOTE_FILE_NAME="remote";/**通过一个给定的路径构建一个配置管理器,该管理器要求地址路径所在目录下必须存在config.properties文件*/privateConfigManager(StringrootPath,StringcontextPath,Stringuri)throwsFileNotFoundException,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()这个方法privatevoidinitEnv()throwsFileNotFoundException,IOException{/****/Filefile=newFile(this.originalPath);if(!file.isAbsolute()){file=newFile(file.getAbsolutePath());}/**获得文件的父路径,也就是..../jsp**/this.parentPath=file.getParent();/**读取配置文件,这个方法比较重要,往下看**/StringconfigContent=this.readFile(this.getConfigPath());try{/**把返回的的json字符串扔进JsonObject对象中**/JSONObjectjsonConfig=newJSONObject(configContent);this.jsonConfig=jsonConfig;}catch(Exceptione){this.jsonConfig=null;}}/**获得配置路径,记住config.json是和controller.jsp放在同一个目录下的,很坑有木有**/privateStringgetConfigPath(){/**拼凑config.json的真实路径**/returnthis.parentPath+File.separator+ConfigManager.configFileName;}privateString[]getArray(Stringkey){JSONArrayjsonArray=this.jsonConfig.getJSONArray(key);String[]result=newString[jsonArray.length()];for(inti=0,len=jsonArray.length();i<len;i++){result[i]=jsonArray.getString(i);}returnresult;}/**获得配置文件的内容,变成字符串返回**/privateStringreadFile(Stringpath)throwsIOException{StringBuilderbuilder=newStringBuilder();try{InputStreamReaderreader=newInputStreamReader(newFileInputStream(path),"UTF-8");BufferedReaderbfReader=newBufferedReader(reader);StringtmpContent=null;while((tmpContent=bfReader.readLine())!=null){builder.append(tmpContent);}bfReader.close();}catch(UnsupportedEncodingExceptione){//忽略}//过滤输入字符串,剔除多行注释以及替换掉反斜杠returnthis.filter(builder.toString());}//过滤输入字符串,剔除多行注释以及替换掉反斜杠privateStringfilter(Stringinput){returninput.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*/publicStringinvoke(){//自己添加上去的Map<string,integer="">mapping=ActionMap.mapping;if(actionType==null||!ActionMap.mapping.containsKey(actionType)){returnnewBaseState(false,AppInfo.INVALID_ACTION).toJSONString();}if(this.configManager==null||!this.configManager.valid()){returnnewBaseState(false,AppInfo.CONFIG_ERROR).toJSONString();}Statestate=null;//获得actionType类型码ActionMap这个类我就不介绍了,自己可以看看,主要是封装的一些常量intactionCode=ActionMap.getType(this.actionType);Map<string,object="">conf=null;switch(actionCode){//如果配置文件,执行下面的方法,这个就是我们开始讲的后端读取的配置文件执行的逻辑caseActionMap.CONFIG:returnthis.configManager.getAllConfig().toString();//这里是我们这次重点讲解的路径,图片上传,视频上传都执行这个路基caseActionMap.UPLOAD_IMAGE:caseActionMap.UPLOAD_SCRAWL:caseActionMap.UPLOAD_VIDEO:caseActionMap.UPLOAD_FILE://发现没有,这里获得配置文件,看到这里,你应该先看getConfig这个方法,跟着思路走,不是是跟着调试代码走conf=this.configManager.getConfig(actionCode);//这里就是执行文件上传的方法了,看完上面代码才可以看这里呀,不要急state=newUploader(request,conf).doExec();break;caseActionMap.CATCH_IMAGE:conf=configManager.getConfig(actionCode);String[]list=this.request.getParameterValues((String)conf.get("fieldName"));state=newImageHunter(conf).capture(list);break;caseActionMap.LIST_IMAGE:caseActionMap.LIST_FILE:conf=configManager.getConfig(actionCode);intstart=this.getStartIndex();state=newFileManager(conf).listFile(start);break;}returnstate.toJSONString();}

看看configManager.getConfig这个类

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

publicJSONObjectgetAllConfig(){returnthis.jsonConfig;}//获得部分的配置publicMap<string,object="">getConfig(inttype){Map<string,object="">conf=newHashMap<string,object="">();StringsavePath=null;switch(type){caseActionMap.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;//上传图片逻辑caseActionMap.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;caseActionMap.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;caseActionMap.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;caseActionMap.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;caseActionMap.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;caseActionMap.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);returnconf;}

接下了这个类Uploader.java

packagecom.baidu.ueditor.upload;importcom.baidu.ueditor.define.State;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;publicclassUploader{privateHttpServletRequestrequest=null;privateMap<string,object="">conf=null;publicUploader(HttpServletRequestrequest,Map<string,object="">conf){this.request=request;this.conf=conf;}publicfinalStatedoExec(){StringfiledName=(String)this.conf.get("fieldName");Statestate=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);}returnstate;}}

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

packagecom.baidu.ueditor.upload;importcom.baidu.ueditor.PathFormat;importcom.baidu.ueditor.define.AppInfo;importcom.baidu.ueditor.define.BaseState;importcom.baidu.ueditor.define.FileType;importcom.baidu.ueditor.define.State;importjava.io.IOException;importjava.io.InputStream;importjava.util.Arrays;importjava.util.List;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;mons.fileupload.FileItemIterator;mons.fileupload.FileItemStream;mons.fileupload.FileUploadException;mons.fileupload.disk.DiskFileItemFactory;mons.fileupload.servlet.ServletFileUpload;publicclassBinaryUploader{publicstaticfinalStatesave(HttpServletRequestrequest,Map<string,object="">conf){FileItemStreamfileStream=null;booleanisAjaxUpload=request.getHeader("X_Requested_With")!=null;if(!ServletFileUpload.isMultipartContent(request)){returnnewBaseState(false,AppInfo.NOT_MULTIPART_CONTENT);}//common-io包中类,用于文件上传ServletFileUploadupload=newServletFileUpload(newDiskFileItemFactory());if(isAjaxUpload){upload.setHeaderEncoding("UTF-8");}try{//获取文件条目FileItemIteratoriterator=upload.getItemIterator(request);while(iterator.hasNext()){fileStream=iterator.next();if(!fileStream.isFormField())break;fileStream=null;}if(fileStream==null){returnnewBaseState(false,AppInfo.NOTFOUND_UPLOAD_DATA);}//获得保存路径StringsavePath=(String)conf.get("savePath");//文件原始名称StringoriginFileName=fileStream.getName();//文件后缀Stringsuffix=FileType.getSuffixByFilename(originFileName);//原文讲原始名称originFileName=originFileName.substring(0,originFileName.length()-suffix.length());savePath=savePath+suffix;longmaxSize=((Long)conf.get("maxSize")).longValue();if(!validType(suffix,(String[])conf.get("allowFiles"))){returnnewBaseState(false,AppInfo.NOT_ALLOW_FILE_TYPE);}savePath=PathFormat.parse(savePath,originFileName);//文件保存的真实物理路径StringphysicalPath=(String)conf.get("rootPath")+savePath;InputStreamis=fileStream.openStream();//这里就是把文件保存到硬盘上,具体怎么保存的可以自己跟过去看看//State这个类很重要,是一个接口,它是返回到前端的数据StatestorageState=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);}returnstorageState;}catch(FileUploadExceptione){returnnewBaseState(false,AppInfo.PARSE_REQUEST_ERROR);}catch(IOExceptione){}returnnewBaseState(false,AppInfo.IO_ERROR);}privatestaticbooleanvalidType(Stringtype,String[]allowTypes){List<string>list=Arrays.asList(allowTypes);returnlist.contains(type);}}

最后,我们再看一个类就是State这个类,它是一个接口,我们主要是看它的实现类BaseState

这个类很重要,很重要,很重要,重要事情说3遍:::

介绍下吧:

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

packagecom.baidu.ueditor.define;importjava.util.HashMap;importjava.util.Iterator;importjava.util.Map;importcom.baidu.ueditor.Encoder;publicclassBaseStateimplementsState{//状态码privatebooleanstate=false;privateStringinfo=null;//里面存保存好的文件路径和privateMap<string,string="">infoMap=newHashMap<string,string="">();publicBaseState(){this.state=true;}publicBaseState(booleanstate){this.setState(state);}publicBaseState(booleanstate,Stringinfo){this.setState(state);this.info=info;}publicBaseState(booleanstate,intinfoCode){this.setState(state);this.info=AppInfo.getStateInfo(infoCode);}publicbooleanisSuccess(){returnthis.state;}publicvoidsetState(booleanstate){this.state=state;}publicvoidsetInfo(Stringinfo){this.info=info;}publicvoidsetInfo(intinfoCode){this.info=AppInfo.getStateInfo(infoCode);}@OverridepublicStringtoJSONString(){returnthis.toString();}/**这里很重要的,也很简单,它把infoMap手工拼凑成json字符串返回回去**/publicStringtoString(){Stringkey=null;StringstateVal=this.isSuccess()?AppInfo.getStateInfo(AppInfo.SUCCESS):this.info;StringBuilderbuilder=newStringBuilder();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("}");returnEncoder.toUnicode(builder.toString());}@OverridepublicvoidputInfo(Stringname,Stringval){this.infoMap.put(name,val);}@OverridepublicvoidputInfo(Stringname,longval){this.putInfo(name,val+"");}}

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

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

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

functioncallback(){try{varlink,json,loader,body=(iframe.contentDocument||iframe.contentWindow.document).body,result=body.innerText||body.textContent||'';//这里result就是后端返回的数据json=(newFunction("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);}functionshowErrorLoader(title){if(loadingId){varloader=me.document.getElementById(loadingId);loader&&domUtils.remove(loader);me.fireEvent('showmessage',{'id':loadingId,'content':title,'type':'error','timeout':4000});}}

参考:/huangwenyi1010/article/details/51637439

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。