H-ui里面集成的是百度的ueditor插件,所以我们这里只说明下ueditor的集成与使用。关于富文本编辑器,对应的选择算是比较多的,比如:fckEditor、kindEditor等,可根据具体的要求来做选择。
1、集成ueditor并在页面中使用
1.1、先将H-ui中的ueditor拷贝到自己的项目中
如下图所示:
需要注意的是,我这里并没有直接直接使用admin/lib目录下面的ueditor包,而是直接复制了一份放在了static当中,这样做只是为了将来拓展时,路径看起来更方便一点,因为不止是后台需要用到ueditor。有一些官网包含一些简单的会员互动,就可以用ueditor的简约版(如果在一个项目的话)。
大家会发现在我们的ueditor文件夹上面有一个小小的红叉,原因是eclipse的编辑校验对json文件的注释不认识,这个只需要更改一下eclipse的json校验就可以,Window——>Preferences——>Validation,具体操作时如图:
![](https://i-blog.csdnimg.cn/blog_migrate/fa3ac3df57046905fcda415ddb1c2b3c.png)
1.2、页面中使用ueditor
我们先在noticeList页面中写好跳转js和控制台的action,如下列图片:
noticeAdd.html页面的代码,只要自己参考一下H-ui的添加页面就可以了。这里就不上完整的代码了,只说明下ueditor的集成方式。在集成thymeleaf时说明过静态资源的根路径是src/main/resource下面的static,所以在当前项目中,页面引入ueditor的路径是:
<script type="text/javascript" th:src="@{/ueditor/1.4.3/ueditor.config.js}"></script>
<script type="text/javascript" th:src="@{/ueditor/1.4.3/ueditor.all.js}"> </script>
<script type="text/javascript" th:src="@{/ueditor/1.4.3/lang/zh-cn/zh-cn.js}"></script>
展示的元素代码如下:
<div class="row cl">
<input type="hidden" id="content" name="content" />
<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>文章内容:</label>
<div class="formControls col-xs-8 col-sm-9">
<script id="editor" type="text/plain" style="width:100%;height:300px;"></script>
</div>
</div>
核心代码就是如下:
<script id="editor" type="text/plain" style="width:100%;height:300px;"></script>
OK到了,这一步,基本的样式展示就可以了,如图:
2、图片、文件上传
对于富文本编辑器的集成难点,我想大概就是在这块,有许多的小伙伴们都知道原理,但就是不知道入口在哪里,加上路径调试的问题,常常让人容易泄气。
目前我们集成的ueditor还不能支持图片上传的功能,原理大家都知道,上传图片是需要调用有效的action的。那么我们先来看看它报什么错!
2.1、ueditor的配置与说明
在1.2小节中,我们看见页面引入了两个非常重要的文件,其中一个是ueditor.config.js,通过名称我们就知道,它是ueditor的配置文件,我们打开看看,你会发现,里面的注释非常的详细(详细的注释是程序员的基本素养)。我们不难找到以下注释:
我们还发现了一个核心的数组配置:window.UEDITOR_CONFIG,我们只要在引入他的页面中打印出来看看它获取到的是什么?在noticeAdd.html中js区写上console.log(window.UEDITOR_CONFIG),刷新下页面,查看控制台,如图:
我们重点看下UEDITOR_HOME_URL和serverUrl的值,发现URL的值是“http://localhost:8090/ueditor/1.4.3”,初始化来至于getUEBasePath()函数(就在当前ueditor.config.js文件中,有时间可以自己查看)。代码调试和读到这里,我们会发现,我们只要修改serverUrl成为可以访问的action就可以了。所以,我们现在需要根据当前引用页面的地址拼接一个根路径:“http://localhost:8090/”。那么我们加这么一个函数getRootUrl,如图:
OK,到了这一步,我们剩下的就是仿照jsp示例封装ueditor的action了。在进行下一步之前,这里拓展一下。
在springboot当中,我们可以配置内置的Tomcat,这其中包括可以配置项目的根路径context-path,如图:
当前,我这里配置的是“/”,所以,以上的自定义函数getRootUrl那么写没有问题,但如果我这里配置的context-path: /timblog,那么,我们的getRootUrl函数就要生成“http://localhost:8090/timblog”。这里就不放代码了,用js截取下pathname就可以。当然,在修改了context-path之后,对应的thymeleaf的基础路径配置也要做相关的修改,这里不赘述。
2.2、改造ueditor的jsp成spring的action
结合上面的配置,我们有了根路径后,接下来就是怎么访问ueditor的action。我们先看看ueditor的目录结构
我们发现,ueditor对于.net、php、java都有对应的处理包。这里明显php就更好用了,直接访问就可以,而对于java的jsp,我们实在不太方便处理。怎么办呢?为了一劳永逸,决定把jsp改造成一个通用的action。怎么改?我们先看看jsp写了些什么,又依赖了些什么jar与类。
有jsp和servlet基础的同学不难发现,jsp中调用了ActionEnter,并且以request和rootPath为参数。那么我们的改造就从这些类开始。
我们先建立好自己的目录结构,我们在common目录下建一个ueditor目录,并把jsp目录中的java文件和文件夹拷贝到当前目录下,修改调试好package路径,如图:
要达到这一步,只要多使用一下ide的技巧就可以。然后,我们发现,类ConfigManager还是报错,看看具体的错误,发现是对应的android-json异常没有处理,我们分别在getConfig与getArray这两个方法中try...catch处理一下,如图:
接下来,我们自定义的一个类UEditorController(在common.ueditor目录之下),这个类该怎么写呢?我们先来看看jsp中关于ActionEnter的源码。我们发现类ActionEnter其实是ueditor的action处理类,如下图所示,在request中,一定会传入一个action的参数,根据action的值,判断并获取对应的配置信息(获取文件jsp/config.json中对应的配置信息):
那么我们自定义ueditor的入口就有思路了,只要写一个spring的action,并且复制jsp中的代码。这里直接上代码:
package com.ruiyi.common.ueditor;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* <p> Title: </p>
* <p> Description: </p>
* @user yangtao
* @date 2020年8月27日
* @版本 1.00
* @修改记录
* <pre>
* 版本 修改人 修改时间 修改内容描述
* ----------------------------------------
* 1.00 yangtao 2020年8月27日 初始化版本
* ----------------------------------------
* </pre>
*/
@Controller
@RequestMapping("/ueditor")
public class UEditorController {
/**
* 将ueditor示例中的jsp访问转换到springMVC中
* */
@RequestMapping("/dispatch")
public void config(HttpServletRequest request,
HttpServletResponse response, String action) {
response.setContentType("application/json");
String rootPath = request.getSession().getServletContext()
.getRealPath("/");
try {
String exec = new ActionEnter(request, rootPath).exec();
PrintWriter writer = response.getWriter();
writer.write(exec);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
然后,我们修改一下ueditor.config.js中的serverUrl访问路径:
到了这一步,对应的图片上传按钮就可以点击了(还不能实现功能),对应的controller.jsp就可以删除了。
2.3、ueditor的初始化与获取config.json简单说明
上一小节,我们完成了对ueditor入口jsp的改造,但还不能使用,我们先看看页面错误。
点击进去,发现一脸懵逼,这怎么调试呢?其实,想想都知道,就算我们的图片上传成功了,图片又保存在哪里呢?所以,我们先要明白,ueditor的处理思路是什么,这就需要我们来看看ueditor的源码了。由于不是视频,我这里不方便演示调试(注意,不方便debug,因为js端在等候断点的时候,会直接报错),就直接说明了。
我们稍微看下ActionEnter的源码,并且打印一下,每次请求的action的值,就不难发现,ueditor的动作都在类ActionEnter做区分与分发,初始化的时候,action传入的值是config,根据ActionEnter中的invoke方法,我们不难找到ConfigManager类。那么到这一步就好办了。再读下ConfigManager类就知道,原来ConfigManager类一直在找一个文件:config.json,并根据config.json中的配置封装各项的值。而ConfigManager类中的方法getConfigPath就是用来获取config.json文件路径的,因此我们只要根据项目中config.json所在的位置,修改一下getConfigPath方法的代码:
ConfigManager类中的getConfigPath方法修改如下:
/**
* update by yangtao
* 根据实际情况,修改获取config.json文件的获取路径
* */
private String getConfigPath () {
// 这是ueditor默认的路径
// return this.parentPath + File.separator + ConfigManager.configFileName;
// roorPath为项目的根目录带"/"号,指到WebRoot下
String resourcePath = StringUtils.replace(this.rootPath, "webapp", "resources");
String path = resourcePath + "static/ueditor/1.4.3" + File.separator + "jsp" + File.separator
+ ConfigManager.configFileName;
return path;
}
再次刷新页面测试一下,不再报错了(还不能真正上传图片,下一小节详细说明)。关于config.json的具体说明,可以直接打开文件查看,注释很详细。
2.4、图片上传的实现
到目前为止,我们梳理到了ueditor的初始化,那么怎么才能上传图片呢?我们先看看目前的图片上传效果。
由上图可以看见,我们的ueditor集成已经没有报错了,但是却还是不能上传图片,报“未找到上传数据”。
继续打印调试,得知图片上传的action对应的值是:uploadimage,通过查看ActionEnter中的invoke方法,图片、视频、文件等的上传都是共用Uploader类中的上传方法。
剩下的事情就只要改造上传的类了,也就是Base64Uploader和BinaryUploader类中的save方法
解读配置源码,我们修改BinaryUploader中的save方法如下,原来的save方法注释掉就可以。
public static final State save(HttpServletRequest request,
Map<String, Object> conf) {
try {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
String savePath = (String) conf.get("savePath");
String originFileName = multipartFile.getOriginalFilename();
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 [] savePathBySplit_temp = savePath.split("/");
String temp = "";
String fileName = savePathBySplit_temp[savePathBySplit_temp.length-1];
for(int i = 1;i < savePathBySplit_temp.length-1; i++){
if(i!=savePathBySplit_temp.length-1){
temp+=savePathBySplit_temp[i]+"/";
}else{
temp+=savePathBySplit_temp[i];
}
}
String rootpath = request.getSession().getServletContext().getRealPath("/");
String pathTemp = rootpath + temp;
File targetFile = new File(pathTemp);
if(!targetFile.exists()){
targetFile.mkdirs();
}
/************/
//State storageState = StorageManager.saveFileByInputStream(multipartFile.getInputStream(),savePath, maxSize);
State storageState = StorageManager.saveFileByInputStream(multipartFile.getInputStream(),pathTemp+"/"+fileName, maxSize);
if (storageState.isSuccess()) {
storageState.putInfo("url", PathFormat.format(savePath));
storageState.putInfo("type", suffix);
storageState.putInfo("original", originFileName + suffix);
}
return storageState;
}catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
return new BaseState(false, AppInfo.IO_ERROR);
}
核心是方法中的这句代码(将文件保存到自己项目的有效目录下):
State storageState = StorageManager.saveFileByInputStream(multipartFile.getInputStream(),pathTemp+"/"+fileName, maxSize);
再次打开Ueditor,图片可以完美上传了。
我这里使用的是config.json中默认的配置,比较冗长,大家可以修改config.json中的值,自定义自己的文件存放目录。
3、多图上传与在线管理
3.1、多图上传
其实,调试好了单图上传的路径、配置等,多图上传就显得格外的简单了。这里直接上示例。大家试试就可以。
3.2、图片在线管理
如果大家是一步一步走到这里的话,那么,你的在线管理应该是显示如下图的状态:
这说明,我们图片确实上传成功了,但是在线管理却没有获取到正确的图片路径。该如何处理呢?有了以往的调试经验,只要找到“在线管理”对应的处理程序就可以了,action的值为:listimage。
找到这里,我们发现原来FileManager默认是找的图片保存的path,也就是图片保存的本地实际地址。我们可以这么操作一下,选中“在线管理”中的一张,然后看下html源码,就是我们图片的本地保存地址了:
因此,思路来了,我们只要将path修改转换成页面浏览器可以访问的url就行。我们这里就不去修改FileManager的源码了,对于已经封装好的类,真是牵一发而动全身。我们在自定义的类UEditorController中,加一段处理listimage的代码就行。这里直接上代码,其中增加的if就是将path转换成url的处理逻辑:
package com.ruiyi.common.ueditor;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* <p> Title: </p>
* <p> Description: </p>
* @user yangtao
* @date 2020年8月27日
* @版本 1.00
* @修改记录
* <pre>
* 版本 修改人 修改时间 修改内容描述
* ----------------------------------------
* 1.00 yangtao 2020年8月27日 初始化版本
* ----------------------------------------
* </pre>
*/
@Controller
@RequestMapping("/ueditor")
public class UEditorController {
private static final String LIST_FILE = "listfile";
private static final String LIST_IMAGE = "listimage";
/**
* 将ueditor示例中的jsp访问转换到springMVC中
* */
@RequestMapping("/dispatch")
public void config(HttpServletRequest request,
HttpServletResponse response, String action) {
//System.out.println("action:" + action);
response.setContentType("application/json");
String rootPath = request.getSession().getServletContext()
.getRealPath("/");
try {
String exec = new ActionEnter(request, rootPath).exec();
/*
* update by yangtao
* 修改“在线管理”图片的访问路径
*/
if (action != null
&& (StringUtils.equals(action, LIST_FILE) || StringUtils.equals(action, LIST_IMAGE))) {
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort() + path + "/";
rootPath = rootPath.replace("\\", "/");
exec = exec.replaceAll(rootPath, basePath);
}
PrintWriter writer = response.getWriter();
writer.write(exec);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
之前上传的图片,就出现了:
4、图片在线删除(拓展)
如果有人问哪些行业容易产生强迫症,个人认为IT行业绝对上榜。调试到以上的步骤,对于ueditor的基本集成已经算是完成了。但有些小伙伴们会想,既然是“在线管理”,那么除了可以增加图片,也应该可以删除图片。最重要的是,这个功能并不是毫无用处,当上传的一些图片没用,或者重复了,这个功能就可以很好发挥了。那么,我们就来实现这个功能,算是一个简单的拓展吧(实现这一步,小伙伴们需要一定的js、jquery、css基础)。
首先,我们来捋一捋删除图片的思路:
1) 修改“在线管理”的图片样式,为每张图片添加一个小红叉;
2) 设计一个js函数事件,点击图片小红叉时触发,并将图片从列表中移除;
3) 请求后台action,根据图片地址,真正删除项目中指定的图片;
有了以上的思路,拓展就很有条理了。
4.1、为每张图片增加一张删除按钮
我们打开ueditor的会话框组件包,找到图片相关的会话框
读一读image.html源码,我们发现在线图片的id是imageList
然后,我们到image.js中寻找对应的处理逻辑。不难发现,通过函数getImageData来加载指定url上的图片。
而单个图片的加载时通过函数pushData
源码读到这里,我们就只要在这个函数里面为每张图片增加一个样式了。具体怎么添加呢?我们先看看图片的样式对应的css选择器是什么样的?在线管理中打开浏览器源码查看:
因此,我们有这么一个思路,在所在的image所在的li中增加一个✖按钮,并且放置在图片的右上角。这里调试样式的过程就不写了,直接上代码,写在image.css的最后:
有了这个样式,我们再在image.js中的pushData函数中添加进去:
大家跟着的代码如果没有敲错,就已经实现以下效果了:
4.2、为删除按钮注册函数事件
到这一步就是js的事情了,我们只要注册一个函数,并且调试相关事件,这里就不多说明,直接上代码:
4.3、ajax请求后台删除图片
上面的js调试逻辑已经很明显了,我们只要在后面的代码加上对应的ajax请求后台就可以,代码如下:
/*
* add by yangtao
* 在线管理图片增加图片删除功能
* */
item.appendChild($("<span class='delbtn' url='" + list[i].url + "'>✖</span>").click(function (){
var del = $(this);
try {
window.event.cancelBubble = true; //停止冒泡
window.event.returnValue = false; //阻止事件的默认行为
window.event.preventDefault(); //取消事件的默认行为
window.event.stopPropagation(); //阻止事件的传播
} finally {//确保逻辑的执行,放置到finally中
var bool = confirm("确定要删除吗?");
if (!bool) return;
$.ajax({
type: "POST",
url:editor.getOpt("serverUrl"), //还记得config.js中的配置吗?
data:{
"action" : "deleteImage",
"imageUrl" : del.attr("url")
},
error: function(request) {
alert("Connection error");
},
success: function(data) {
if(data){
del.parent().remove();
}else{
alert("删除失败");
}
}
});
}
})[0]);
所以,我们这里的请求还是config.js中的全局配置,参数我们自定义了action的值为deleteImage
剩下的逻辑就是我们自定义的UEditorController的了。这里我也直接上代码,用一个if做相关的处理
package com.ruiyi.common.ueditor;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* <p> Title: </p>
* <p> Description: </p>
* @user yangtao
* @date 2020年8月27日
* @版本 1.00
* @修改记录
* <pre>
* 版本 修改人 修改时间 修改内容描述
* ----------------------------------------
* 1.00 yangtao 2020年8月27日 初始化版本
* ----------------------------------------
* </pre>
*/
@Controller
@RequestMapping("/ueditor")
public class UEditorController {
private static final String LIST_FILE = "listfile";
private static final String LIST_IMAGE = "listimage";
private static final String DELETE_IMAGE = "deleteImage";
/**
* 将ueditor示例中的jsp访问转换到springMVC中
* */
@RequestMapping("/dispatch")
public void config(HttpServletRequest request,
HttpServletResponse response, String action) {
response.setContentType("application/json");
String rootPath = request.getSession().getServletContext()
.getRealPath("/");
try {
/*
* 在线管理图片,删除图片功能
* */
if (action != null && StringUtils.equals(action, DELETE_IMAGE)) {
String imageUrl = request.getParameter("imageUrl");
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort() + path + "/";
rootPath = rootPath.replace("\\", "/");
String imagePath = imageUrl.replaceAll(basePath, rootPath);
File file = new File(imagePath);
boolean delflag = file.delete();
PrintWriter writer = response.getWriter();
writer.write(String.valueOf(delflag));
writer.flush();
writer.close();
return;
}
String exec = new ActionEnter(request, rootPath).exec();
/*
* update by yangtao
* 修改“在线管理”图片的访问路径
*/
if (action != null
&& (StringUtils.equals(action, LIST_FILE) || StringUtils.equals(action, LIST_IMAGE))) {
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort() + path + "/";
rootPath = rootPath.replace("\\", "/");
exec = exec.replaceAll(rootPath, basePath);
}
PrintWriter writer = response.getWriter();
writer.write(exec);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
到这一步,调试好删除路径与url的对应关系,删除功能就完成了。需要注意的是,我们这里的删除图片纯粹是针对项目上的资源。实际项目中,上传图片时,会将图片的url保存在数据库中,那么删除的时候就要注意了,需要做对应的判断,保证数据的原子性。
5、ueditor图片、文件上传到云空间
在互联网迅速发展的今天,网络资源的迅速增长、泛滥,催生了云空间这类的统一管理技术。那么我们的系统资源不再单单的只在自己的服务器上了,如果要共享到别的子系统,云空间格外的方便。各大平台的OBS(对象存储服务)都会提供对应的接口,我们这里以七牛云为例。
小伙伴们根据自己的需要,先在七牛云官网申请到对应的空间,获取到ACCESS_KEY和SECRET_KEY,并指定对应的空间和目录。这里我就直接上相关的资源和代码:
七牛云所需的坐标,版本自行和自己使用的springboot适配
<!-- 七牛云相关jar -->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.2.11</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>happy-dns-java</artifactId>
<version>0.1.4</version>
<scope>compile</scope>
</dependency>
编写七牛云公共util代码(网上很多资源的):
package com.ruiyi.common.util;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.ruiyi.common.ConstantConfig;
/**
* <p> Title: </p>
* <p> Description: </p>
* @user yangtao
* @date 2019年5月7日
* @版本 1.00
* @修改记录
* <pre>
* 版本 修改人 修改时间 修改内容描述
* ----------------------------------------
* 1.00 yangtao 2019年5月7日 初始化版本
* ----------------------------------------
* </pre>
*/
public class QiniuyunUtil {
private static Logger logger = LoggerFactory.getLogger(QiniuyunUtil.class);
//设置好账号的ACCESS_KEY和SECRET_KEY
private static final String ACCESS_KEY = ConstantConfig.QINIU_ACCESS_KEY; //这两个登录七牛 账号里面可以找到
private static final String SECRET_KEY = ConstantConfig.QINIU_SECRET_KEY;
//要上传的空间
private static final String BUCKET_NAME =ConstantConfig.QINIU_BUCKET;
private static final String DOMAIN = ConstantConfig.QINIUYUN_URL;
//密钥配置
private static Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
private static Configuration cfg = new Configuration(Zone.huanan());
//创建上传对象
private static UploadManager uploadManager = new UploadManager(cfg);
//简单上传,使用默认策略,只需要设置上传的空间名就可以了
public static String getUpToken(){
return auth.uploadToken(BUCKET_NAME);
}
public static String UploadPic(String FilePath,String FileName){
Configuration cfg = new Configuration(Zone.huanan());
UploadManager uploadManager = new UploadManager(cfg);
String accessKey = ACCESS_KEY; //AccessKey的值
String secretKey = SECRET_KEY; //SecretKey的值
String bucket = BUCKET_NAME; //存储空间名
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
Response response = uploadManager.put(FilePath, FileName, upToken);
//解析上传成功的结果
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
System.out.println(putRet.key);
System.out.println(putRet.hash);
return DOMAIN+FileName;
}catch (QiniuException ex){
logger.error(ex.getMessage());
}
return null;
}
/**
* 上传web式MultipartFile类型的文件
* @param file 上传的MultipartFile文件
* @param filename 上传到七牛云上的文件名(时间戳 + 2位随机数)
* */
public static String updateMultipartFile(MultipartFile file, String filename) {
//默认不指定key的情况下,以文件内容的hash值作为文件名
InputStream inputStream = null;
ByteArrayOutputStream swapStream = null;
//解析上传成功的结果
DefaultPutRet putRet = null;
try {
inputStream = file.getInputStream();
swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[1024]; //buff用于存放循环读取的临时数据
int rc = 0;
while ((rc = inputStream.read(buff, 0, 128)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] uploadBytes = swapStream.toByteArray();
Response response = uploadManager.put(uploadBytes,filename,getUpToken());
putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
return DOMAIN + putRet.key;
} catch (QiniuException ex) {
logger.error(ex.response.toString());
} catch (UnsupportedEncodingException ex) {
logger.error(ex.getMessage());
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
if(swapStream != null) {
try {
swapStream.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
}
return null;
}
/**
* 下载公有图片文件
*
* */
public static BufferedImage downloadImage(String imageUrl) {
URL url = null;
HttpURLConnection conn = null;
DataInputStream dataInputStream = null;
BufferedInputStream bufferedInputStream = null;
BufferedImage preImage = null;
try {
url = new URL(imageUrl);
conn = (HttpURLConnection)url.openConnection();
//设置超时时间为3秒
conn.setConnectTimeout(3*1000);
//防止屏蔽程序抓取而返回403错误
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
//1.获取url的输入流 dataInputStream
dataInputStream = new DataInputStream(url.openStream());
//2.加一层BufferedInputStream
bufferedInputStream = new BufferedInputStream(dataInputStream);
//3.构造原始图片流 preImage
preImage = ImageIO.read(bufferedInputStream);
} catch (MalformedURLException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
} finally {
if(dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
if(bufferedInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
}
return preImage;
}
}
有了这些工具,剩下的事情非常的简单,只要修改一下ueditor中上传文件的方法使用七牛云的就可以了,具体只要修改BinaryUploader类中的save方法了,不过,为了类的通用性,我们增加一个方法qiniuyunSave(复制一份save,然后改造)
public static final State qiniuyunSave(HttpServletRequest request,
Map<String, Object> conf) {
try {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
String savePath = (String) conf.get("savePath");
String originFileName = multipartFile.getOriginalFilename();
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);
InputStream is = multipartFile.getInputStream();
/**
* 上传到七牛云
*/
// *******************开始***********************
String fileName = new StringBuffer().append(new Date().getTime())
.append(savePath.substring(savePath.indexOf("."))).toString();
State storageState = null;
try {
//上传到七牛云
QiniuyunUtil.updateMultipartFile(multipartFile, fileName);
storageState = StorageManager.saveFileByInputStream(is, fileName, maxSize);
storageState.putInfo("state", "SUCCESS");
// url:返回前端的访问路径,请根据自己实际情况填写
storageState.putInfo("url", ConstantConfig.QINIUYUN_URL + fileName);
storageState.putInfo("title", fileName);
storageState.putInfo("original", fileName);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
storageState.putInfo("state", "文件上传失败!");
storageState.putInfo("url", "");
storageState.putInfo("title", "");
storageState.putInfo("original", "");
// System.out.println("文件 "+fileName+" 上传失败!");
}
// ********************结束**********************
is.close();
return storageState;
} catch (IOException e) {
}
return new BaseState(false, AppInfo.IO_ERROR);
}
然后,在类Uploader中换成七牛云的这个方法就可以了 测试一下,成功后查看一下,这个网址就是七牛云对应的访问地址了。
至于删除,这里就不多加赘述了,弄通了第4小节的内容,重构起来非常简单。
6、ueditor的一些其它说明
6.1、form表单怎么获取ueditor内容?
回到curd的逻辑,页面集成的ueditor,怎么将内容获取,并保存到数据库中?要知道,我们的ueditor是一个script标签。这里我们设计一个隐藏域,将值通过js赋进去就行
var ue = UE.getEditor('editor');
//将uEditor中的内容赋值到content中
var content=ue.getContent();
$("#content").val(content);
6.2、如何让ueditor不可编辑(查看页面)?
var ue=new UE.ui.Editor({readonly:true,});
ue.render('editor');
总结:
内容有点多,这篇博文做一个小小的总结
1、复制全ueditor包到自定的路径;
2、配置好ueditor.config.js中的servletUrl
3、改造ueditor.jsp成springboot的controller
4、调试图片的保存路径(一定要弄清楚)
5、拓展图片删除功能
6、图片上传与云空间的对接
以上就是关于ueditor集成的全部内容,个人觉得算是比较全面了,请仔细阅读与调试。下一节我们来集成一下webuploader,我们下节见。