概述
最近自己做的一个内容管理平台,客户需要集成秀米编辑器,查看了秀米官方文档,仅支持ueditor内核的编辑器才行,这边不得不吐槽一下百度这款开源的产品BUG真是太多了。随便一搜CSDN都是踩坑日记,各种修改js,最后可能还是有各种隐藏的坑在里面。
UeditorPlus是Ueditor一个重构的版本,之前的应该也不维护了,BUG实在太多了。
下面的文章是基于vue + UeditorPlus集成秀米编辑器为例来说一下如何用java 实现图片的转储功能。
官方文档
vue-ueditor-wrap Vue UEditor插件
1. 集成UeditorPlus
前端接入基于vue插件接入非常简单, (1) 安装UEditor插件
npm i vue-ueditor-wrap
(2) 解压 UEditorPlus 到静态资源目录,配置
<script>
import VueUeditorWrap from "vue-ueditor-wrap";
import SingleUpload from '@/components/Upload/singleUpload'
import {getNewsById} from '@/api/getNews'
const defaultNews = {
id:'',
title: '',
coverImg: '',
content: ''
};
export default {
name: 'newsDetail',
components: { VueUeditorWrap, SingleUpload },
data() {
return {
newsParam: Object.assign({}, defaultNews),
content: 'Welcome to Your Vue.js App',
editorConfig: {
// 相对路径
UEDITOR_HOME_URL: '/static/UEditorPlus/',
serverUrl: "http://1.13.22.158:8080/ueditor/cos",
toolbars: [[
'insertvideo',
'xiumi-dialog'
]],
catchRemoteImageEnable: false, //设置是否抓取远程图片
paths: {
ZeroClipboard: "/static/UEditorPlus/ZeroClipboard"
},
// 编辑器不自动被内容撑高
autoHeightEnabled: false,
// 初始容器高度// 初始容器宽度
initialFrameHeight: 400,
initialFrameWidth: '100%'
}
};
},
created(){
getNewsById(this.$route.query.id).then(response=>{
this.newsParam=response.data;
});
},
methods: {
addXiumiDialog(editorId) {
window.UE.registerUI(
'xiumi-dialog',
(editor, uiName) => {
// 创建 “秀米弹窗”
const dialog = new window.UE.ui.Dialog({
// 注意:这是 xiumi-ue-dialog-v5.html 文件的访问链接,这个页面会通过 iframe 的方式嵌入到弹窗里
iframeUrl: '/static/UEditorPlus/xiumi-ue-dialog-v5.html',
editor,
name: uiName,
title: '秀米图文消息助手',
cssRules: 'width: ' + (window.innerWidth - 60) + 'px; height: ' + (window.innerHeight - 60) + 'px;',
});
// 添加自定义按钮用于唤起“秀米弹窗”
const btn = new window.UE.ui.Button({
name: 'xiumi-connect',
title: '秀米',
cssRules: `background-image: url('//dl.xiumi.us/connect/ue/xiumi-connect-icon.png') !important; background-size: contain;`,
onclick() {
dialog.render();
dialog.open();
},
});
return btn;
},
2 /* 指定添加到工具栏上的那个位置,默认时追加到最后 */,
editorId /* 指定这个UI是哪个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮 */
);
}
}
}
</script>
2. 集成秀米编辑器
官网推荐的before-init钩子函数进行秀米编辑器的集成。参考上面的代码
methods: {
addXiumiDialog(editorId) {
window.UE.registerUI(
'xiumi-dialog',
(editor, uiName) => {
// 创建 “秀米弹窗”
const dialog = new window.UE.ui.Dialog({
// 注意:这是 xiumi-ue-dialog-v5.html 文件的访问链接,这个页面会通过 iframe 的方式嵌入到弹窗里
iframeUrl: '/static/UEditorPlus/xiumi-ue-dialog-v5.html',
editor,
name: uiName,
title: '秀米图文消息助手',
cssRules: 'width: ' + (window.innerWidth - 60) + 'px; height: ' + (window.innerHeight - 60) + 'px;',
});
// 添加自定义按钮用于唤起“秀米弹窗”
const btn = new window.UE.ui.Button({
name: 'xiumi-connect',
title: '秀米',
cssRules: `background-image: url('//dl.xiumi.us/connect/ue/xiumi-connect-icon.png') !important; background-size: contain;`,
onclick() {
dialog.render();
dialog.open();
},
});
return btn;
},
2 /* 指定添加到工具栏上的那个位置,默认时追加到最后 */,
editorId /* 指定这个UI是哪个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮 */
);
}
}
3. java后端接口转存
参考官方文档: 后端部署说明
我这边是提供一个后端接口,将秀米图片文件或者视频链接文件上传到自己的minio服务器上。具体代码如下:
package com.xx.news.platform.modules.admin.controller;
import com.xx.news.platform.modules.admin.dto.Ueditor;
import com.xx.news.platform.modules.admin.service.MinioService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@RequestMapping("/ueditor")
@Controller
@CrossOrigin
public class UeditorController {
@Resource
private MinioService minioService;
@RequestMapping(value = "/cos")
@ResponseBody
public Object server(String action, String callback, MultipartFile upfile, HttpServletResponse response) {
Object result = null;
switch (action) {
case Ueditor.ACTION_CONFIG:
String result1 = "";
if (callback != null) {
result1 = callback + "(" + Ueditor.UEDITOR_CONFIG + ")";
} else {
result1 = Ueditor.UEDITOR_CONFIG;
}
try {
response.getWriter().write(result1);//返回的十回调函数
} catch (IOException e) {
e.printStackTrace();
}
break;
case Ueditor.ACTION_UPLOADFILE:
case Ueditor.ACTION_UPLOADVIDEO:
case Ueditor.ACTION_UPLOADIMAGE:
String url = minioService.upload(upfile);
Ueditor ueditor = new Ueditor();
ueditor.setUrl(url);
ueditor.setState(Ueditor.ACTION_SUCCESS);
ueditor.setTitle(upfile.getOriginalFilename());
result = ueditor;
break;
default:
}
return result;
}
}
package com.xx.news.platform.modules.admin.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.xx.news.platform.modules.admin.service.MinioService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
@Service
public class MinioServiceImpl implements MinioService {
@Value("${minio.endpoint}")
private String ENDPOINT;
@Value("${minio.bucketName}")
private String BUCKET_NAME;
@Value("${minio.accessKey}")
private String ACCESS_KEY;
@Value("${minio.secretKey}")
private String SECRET_KEY;
@Value("${minio.tempPath}")
private String tempPath;
@Override
public String upload(String imgUrl) {
try {
//创建一个MinIO的Java客户端
MinioClient minioClient =MinioClient.builder()
.endpoint(ENDPOINT)
.credentials(ACCESS_KEY,SECRET_KEY)
.build();
File imgFile = HttpUtil.downloadFileFromUrl(imgUrl, tempPath);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 设置存储对象名称
String objectName = sdf.format(new Date()) + "/" + imgFile.getName();
// 使用putObject上传一个文件到存储桶中
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(BUCKET_NAME)
.object(objectName)
.stream(FileUtil.getInputStream(imgFile), imgFile.length(), -1).build();
minioClient.putObject(putObjectArgs);
String minioURL = ENDPOINT + "/" + BUCKET_NAME + "/" + objectName;
log.info("文件上传成功, minioURL:{}!", minioURL);
return minioURL;
} catch (Exception e) {
log.info("上传到minio文件出现异常", e);
}
return null;
}
@Override
public String upload(MultipartFile file) {
try {
//创建一个MinIO的Java客户端
MinioClient minioClient =MinioClient.builder()
.endpoint(ENDPOINT)
.credentials(ACCESS_KEY,SECRET_KEY)
.build();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 设置存储对象名称
String objectName = sdf.format(new Date()) + "/" + file.getOriginalFilename();
// 使用putObject上传一个文件到存储桶中
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(BUCKET_NAME)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1).build();
minioClient.putObject(putObjectArgs);
String minioURL = ENDPOINT + "/" + BUCKET_NAME + "/" + objectName;
log.info("文件上传成功, minioURL:{}!", minioURL);
return minioURL;
} catch (Exception e) {
log.info("上传到minio文件出现异常", e);
}
return null;
}
}
最后
目前这个内容管理平台已经放在git上面了,如果有帮助欢迎大家关注和点赞。有什么不正确的也欢迎大家指正。
前端地址:xx-web
后端项目地址:xx-admin 后台管理系统