Ueditor 百度强大富文本Springboot 项目集成使用(包含上传文件和上传图片的功能使用)简单易懂,举一反三

Ueditor 百度强大富文本Springboot 项目集成使用

  • 首先如果大家的富文本中不考虑图片或者附件的情况下,只考虑纯文本且排版的情况下我们可以直接让前端的vue来继承UEditor就可以啦。但是要让前端将那几个上传图片和附件的哪些功能给阉割掉!

  • 然后就是说如果考虑到了上传图片或者视频和附件那么咱们还是用的前后分离的项目,那么我们就需要后台去做一些调整来职称前端上传了功能啦。(市面上有很多富文本编辑器,而且现在的UEditor的前端UI是很丑的,因为现在都2023年啦。但是耐不住人家功能丰富而且免费),那么我刚开始了解的这个也是无从下手,在众多博客和文档中找到了一条出路然后随便做下笔记,让大家不在急躁乏味奥利给!

  • 我在网上看了一大推的资料发现有很多不一样的案例实现,但是说的不是复杂就是特别的简单且抽象无从下手,废话不多说怎怎么直接开始

    首先我们去官网,咱们将zip包下载下来之后解压,注意要下载JSP使用说明的那个链接的zip包,因为他是github可能打不开链接地址,那么就可以去maven 去下载,但是maven下载的只有咱们后台用到的,前端的就要还是去官网下载,然后maven也写在这里啦

<!-- https://mvnrepository.com/artifact/com.gitee.qdbp.thirdparty/ueditor -->
<dependency>
    <groupId>com.gitee.qdbp.thirdparty</groupId>
    <artifactId>ueditor</artifactId>
    <version>1.4.3.6</version>
</dependency>

官网下载地址
在这里插入图片描述

然后在jsp中里面会存在一个 lib文件夹,然后是里面是有一个是config.json 这个是比较重要的一个配置文件一会我们回去修改其中的内容信息,纳闷我们现在将需要的jar包考出来是,就在lib 下面 


将文件引入到项目之中的resouces/lib 下 然后添加xml文件的依赖

<dependency>
    <groupId>com.gitee.qdbp.thirdparty</groupId>
    <artifactId>ueditor</artifactId>
    <version>1.4.3.6</version>
    <classifier>lib</classifier>
    <scope>system</scope>
    <systemPath>${project.basedir}/src/main/resources/lib/ueditor-1.4.3.6.jar</systemPath>
</dependency>

在这里插入图片描述

  • 好的现在已经完成了很大一部分啦,后面就是需要写代码啦。啦啦啦
    首先大家要是试过Ueditor的官网demo之后会发现会调用一个config 的接口,但是现在是没有这个接口的,而且这个接口是一个 根据不同的请求参数来表示不同的请求 比如: config?action=config 初始化,config?action=uploadimage 上传图片,config?action=uploadfile 上传文件 这个则初始化后台的一个接口就相当于进屋要先拿钥匙开门,然后才能操作 上传功能要不然前段的上传图片连弹框都弹不出来。那么这个钥匙就是要从我们后面获取,每次进入都要调用config?action=config 初始化。

在这里插入图片描述

Controller
控制层中只需要注意action 的参数名称 里面有三个 config,uploadimage,uploadfile 其实上传文件和图片只是存储路径不一样,这个参数并不是咱们定义的而是在上面所说的config.json,我将其中的无用配置删掉啦就留下了 上传图片和文件的
这里原文件中有注释大家可以看一下,所以咱们得那个接口参数就是这些,要是咱们接口名称或者传参的参数名称不叫这个,咱们就需要让两者保持一致。

/**
 * Ueditor富文本控制层
 * @author ZMH
 * @date 24/7/2023 2:33 下午
 */
@Slf4j
@RestController
@RequestMapping("/ueditor")
public class UEditorController {

    @Autowired
    private UEditorUpload uEditorUpload;

    @PassToKen
    @RequestMapping("/config")
    public String exec(HttpServletRequest request,
                       HttpServletResponse response,
                       @RequestParam(value = "action") String action,
                       @RequestParam(value = "upfile", required = false) MultipartFile upfile) throws Exception {
        if (action.equals("config")) {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html");
            String rootPath = request.getSession().getServletContext().getRealPath("/");
            return new ActionEnter(request, rootPath).exec();
        } else if (action.equals("uploadimage")) {
            UEditorFileVo uEditorFile = uEditorUpload.uploadImage(upfile);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(uEditorFile));
            return jsonObject.toJSONString();
        } else if (action.equals("uploadfile")) {
            UEditorFileVo uEditorFile = uEditorUpload.uploadFile(upfile);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(uEditorFile));
            return jsonObject.toJSONString();
        }
        return "无效Action";
    }
}

service
这里我就写了两个上传其实其他的和这个一样只不过多一样,就是上传到服务器上然后返回相应的东西足以让前端展示就可以啦。

/**
 * Ueditor上传
 * @author ZMH
 */
@Service
@Slf4j
public class UEditorUpload {

    @Value("${path.ueditor}")
    private String ueditorFilePath;//ueditor文件存储路径

    /**
     * 上传image
     * @author ZMH
     * @param file
     * @return UEditorFile
     */
    public UEditorFileVo uploadImage(MultipartFile file) throws IOException, BaseException {
        log.info("UEditor开始上传文件");
        if (ObjectUtils.isEmpty(file)){
            log.warn("upfile 文件不能为空!");
            throw new BaseException("upfile 文件不能为空!");
        }
        String fileName = file.getOriginalFilename();  //获取文件名
        //Ueditor的config.json规定的返回路径格式 上传成功之后会返回returnPath
        String returnPath = "/upload/image/"+new Date().getTime()+"/"+fileName;
        File saveFile = new File(ueditorFilePath+returnPath);
        if (!saveFile.exists()){
            saveFile.mkdirs();
        }
        file.transferTo(saveFile);
        log.info("UEditor上传文件成功,保存路径:"+saveFile.getAbsolutePath());
        UEditorFileVo uEditorFile = new UEditorFileVo();
        uEditorFile.setState("SUCCESS");
        uEditorFile.setUrl(returnPath);  //访问URL
        uEditorFile.setTitle(fileName);
        uEditorFile.setOriginal(fileName);
        return uEditorFile;
    }

    /**
     * 上传文件
     * @author ZMH
     * @param file
     * @return UEditorFile
     */
    public UEditorFileVo uploadFile(MultipartFile file) throws IOException, BaseException {
        log.info("UEditor开始上传文件");
        if (ObjectUtils.isEmpty(file)){
            log.warn("upfile 文件不能为空!");
            throw  new BaseException("upfile 文件不能为空!");
        }
        String fileName = file.getOriginalFilename();  //获取文件名
        //Ueditor的config.json规定的返回路径格式
        String returnPath = "/upload/file/"+new Date().getTime()+"/"+fileName;
        File saveFile = new File(ueditorFilePath+returnPath);
        if (!saveFile.exists()){
            saveFile.mkdirs();
        }
        file.transferTo(saveFile);
        log.info("UEditor上传文件成功,保存路径:"+saveFile.getAbsolutePath());
        UEditorFileVo uEditorFile = new UEditorFileVo();
        uEditorFile.setState("SUCCESS");
        uEditorFile.setUrl(returnPath);  //访问URL
        uEditorFile.setTitle(fileName);
        uEditorFile.setOriginal(fileName);
        return uEditorFile;
    }

}

实体类 uEditorFile


/**
 * UEditorFileVo
 * @author ZMH
 */
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class UEditorFileVo {

    private static final long serialVersionUID=1L;

    private String state;

    private String url;

    private String title;

    private String original;

    @Override
    public String toString() {
        return "{" +
                "state='" + state + '\'' +
                ", url='" + url + '\'' +
                ", title='" + title + '\'' +
                ", original='" + original + '\'' +
                '}';
    }
}

到这里已经将代码层面改好啦,然后呢就是最恶心的环节啦,那就是他们的源码里参了一点点西东,那就是BUG,那就是在这个jar包中的 getConfigPath() 方法,这里的获取config路径是不对的,我们需要改一下这个代码,可以使用修改源码或者重写来修改这里的源码,重写就是依靠java 的类加载器如果本地有就去加载本地的类,如果本地没有就去加载其他的,这里我是修改源码实现的。这里就不用大家改了怕累着大少爷,那既然是为大少爷做事,就要优雅。
这里是我改完的源码百度网盘链接: https://pan.baidu.com/s/1tU0uD1IwrMH2Xidcf5h0Dw?pwd=38vc 提取码: 38vc 如果大家好奇我改的什么idea会有对比功能,可以查看一下。其实就是换了获取config.json的路径变为了动态,下载了之后换掉lib下的包。

//在启动类中加入
//对应的配置文件也要有path.ueditorConfigPath 参数信息
@Value("${path.ueditorConfigPath}")
private String ueditorConfigPath;

//main中加入
System.setProperty("ueditor_config_path",ueditorConfigPath);
  • 到这里就可以上传啦,但是回显没有成功,回显其实就是上传成功之后的 url 和咱们初始化的 config 里面的 前缀也就是
    fileUrlPrefix的值和imageUrlPrefix的值,拼起来就可以啦。这里我采用的nginx,到这里也就结束啦。
    然后说一下不推荐的方式,不推荐纯后台集成,不推荐将config.json和保存的路径放在resouces下,这样会导致在本地可以访问到config.json,打完包之后是访问不到的,路径是jar包之内的路径,如果大家初始化有问题,那就记得去打印下你们的config.json
    路径,然后去顺着找一下看看存不存,还有就是一个那个上传到 resouces下的附件虽然说不用去开nginx 直接可以通过
    项目的地址加文件地址可以预览但是呢,就会导致后续发的jar包将之前的内容覆盖掉,导致内容丢失。还是建议大家分开,然后就是这个config.json
    到时候前端是直接将这个模块扔到VUE项目中的,我可以引用前端的config.json。改为前端的config.json地址既可,那样保持一套还好维护
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/47814.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringMvc+Mybatis完整项目

0目录 1.SpringmybatisSpringmvc查询功能&#xff08;记录数&#xff09; 2.查询所有 3.增删改查&#xff08;根据id&#xff09; 4.增加用户注册登录功能 1.SpringmybatisSpringmvc增删改查 新建数据库 创建工程 配置web.xml 配置applicationContext.xml 实体类 My…

SpringBoot 配置⽂件

1.配置文件作用 整个项⽬中所有重要的数据都是在配置⽂件中配置的&#xff0c;⽐如&#xff1a; 数据库的连接信息&#xff08;包含⽤户名和密码的设置&#xff09;&#xff1b;项⽬的启动端⼝&#xff1b;第三⽅系统的调⽤秘钥等信息&#xff1b;⽤于发现和定位问题的普通⽇…

EMP-SSL: TOWARDS SELF-SUPERVISED LEARNING IN ONETRAINING EPOCH

Recently, self-supervised learning (SSL) has achieved tremendous success in learning image representation. Despite the empirical success, most self-supervised learning methods are rather “inefficient” learners, typically taking hundreds of training epoch…

MySQL高可用之MHA集群

目录 一、MHA概述 1.1 什么是 MHA 1.2 MHA 的组成 1.3 MHA 的特点 二、MySQL MHA搭建准备 2.1 实验思路 2.2 实验准备 MHA一主两从高可用集群示意图&#xff1a; 三、搭建 MySQL MHA 3.1 配置主从复制 1、四台服务器都关闭防火墙 2、修改 Master、Slave1、Slave2 节…

汇编调用C语言定义的全局变量

在threadx移植中&#xff0c;系统的systick通过了宏定义的方式定义&#xff0c;很难对接库函数的时钟频率&#xff0c;不太利于进行维护 所以在C文件中自己定义了一个systick_Div的变量&#xff0c;通过宏定义方式设定systick的时钟频率 在汇编下要加载这个systick分频系数 …

STM32 串口基础知识学习

串行/并行通信 串行通信&#xff1a;数据逐位按顺序依次传输。 并行通信&#xff1a;数据各位通过多条线同时传输。 对比 传输速率&#xff1a;串行通信较低&#xff0c;并行通信较高。抗干扰能力&#xff1a;串行通信较强&#xff0c;并行通信较弱。通信距离&#xff1a;串…

在Windows server 2012上使用virtualBox运行CentOS7虚拟机,被强制休眠(二)

问题场景 本月7月10日处理了一个虚拟机被强制暂停的问题&#xff0c;详见&#xff1a;在Windows server 2012上使用virtualBox运行CentOS7虚拟机&#xff0c;被强制暂停当时是由于C盘存储空间不足&#xff0c;导致虚拟机被强制暂停&#xff0c;将虚拟机迁移后&#xff0c;问题…

Mybatis-plus 配置自定义sql(.xml文件)查询语句的步骤

这是使用Mybatis-plus 的自动生成实体类代码生成.xml文件&#xff0c; 所以他会在java目录下&#xff0c;不在resources目录下 如果在java目录下的xml文件&#xff0c;需要分别配置application.yml和pom.xml文件 application.yml 文件进行以下配置&#xff1a; mybatis-plus…

【C刷题】矩阵相等判断与序列中删除指定的数字

目录 BC105-矩阵相等判断 方法1:两矩阵输入完毕后&#xff0c;进行比较 方法2:在接收过程中直接比较 BC98 - 序列中删除指定的数字 方法1:把要删除的元素改为0 方法2:打印不用删除的元素 方法3:定义两个下标 i 和 j(动图演示) 此篇文章是关于牛客网刷题的做题思路和代码…

Docker的数据管理和Dockerfile的指令

Docker的数据管理 一、Docker数据的概念1、数据卷2、数据卷容器 二、端口映射三、容器互联&#xff08;使用centos镜像&#xff09;四、Docker 镜像的创建1、基于现有镜像创建&#xff08;1&#xff09;首先启动一个镜像&#xff0c;在容器里做修改&#xff08;2&#xff09;然…

记录Selenium自动化测试过程中接口的调用信息

上一篇博客&#xff0c;我写了python自动化框架的一些知识和粗浅的看法&#xff0c;在上一篇中我也给自己提出一个需求&#xff1a;如果记录在测试过程中接口的调用情况&#xff1f;提出这个需求&#xff0c;我觉得是有意义的。你在测试过程中肯定会遇到一些莫名其妙的问题&…

K8S故障排查

故障现象&#xff1a;部署pod时&#xff0c;报错没发调度到节点。 排查步骤&#xff1a; 1、查看集群的状态 [rootk8s-master1 nginx]#kubectl get nodes2、查看k8s组件的状态-kubelet&#xff0c;kube-apiservice 3、查看docker的Cgroup driver和k8s的Cgroup driver类型&…

创建Electron项目

一、使用vite 构建 electron项目 npm init vitelatest Need to install the following packages:create-vitelatest Ok to proceed? (y) y √ Project name: ... CertificateDownload √ Package name: ... certificatedownload √ Select a framework: Vue √ Select a var…

Packet Tracer - 配置和验证 NTP

Packet Tracer - 配置和验证 NTP 地址分配表 设备 接口 IP 地址 子网掩码 N1 NIC 209.165.200.225 255.255.255.0 R1 G0/0 209.165.200.226 255.255.255.0 R2 G0/0 209.165.200.227 255.255.255.0 目标 在本练习中&#xff0c;您将在 R1 和 R2 中配置 NTP 以…

1.react useState使用与常见问题

文章目录 0. 取消批处理合并更新, render 2次1. 合并更新,setCount(异步更新) 3次相当于1次, count值为12. 如何取消批处理合并,让值累加?,改为回调函数写法,内部会依次执行函数, 执行3次 count值为33. 异步更新,获取异步更新的值?useEffect4.利用扩展运算符的形式来解决对象…

NSS [SWPUCTF 2021 新生赛]pop

NSS [SWPUCTF 2021 新生赛]pop 倒推一下&#xff0c;最后一步是调用getflag函数&#xff0c;admin和password要求为w44m和08067。 第一步应该从w22m类的魔术方法__destruct()入手&#xff0c;所以中间第二步应该是w33m&#xff08;第一步w22m类的魔术方法__destruct()里面的ec…

【LeetCode热题100】打卡第44天:倒数第30~25题

文章目录 【LeetCode热题100】打卡第44天&#xff1a;倒数第30~25题⛅前言 移动零&#x1f512;题目&#x1f511;题解 寻找重复数&#x1f512;题目&#x1f511;题解 二叉树的序列化与反序列化&#x1f512;题目&#x1f511;题解 最长递增子序列&#x1f512;题目&#x1f5…

pytorch分类和回归:阿里天池宠物年龄预测

文章目录 dog年龄预测论文Deep expectation of real and apparent age from a single image without facial landmarks分类的损失函数1.多分类交叉熵损失函数&#xff1a;2.KLDiv Loss&#xff1a; 分布差异3.facenet 三元组损失函数 timm and torchvisiontorchvision 尝试一&a…

全面防护!Fortinet发布混合式部署防火墙HMF

在企业IT复杂性日益增长、网络安全威胁日趋紧迫、网络安全设施可维护性逐渐降低的背景下&#xff0c;企业迫切寻求可无缝跨越所有IT区域&#xff0c;有效简化企业防护架构的统一解决方案。近日&#xff0c; Fortinet Accelerate 2023中国区15城巡展圆满落幕&#xff0c;在收官之…

SpringBoot 项目使用 Redis 对用户 IP 进行接口限流

一、思路 使用接口限流的主要目的在于提高系统的稳定性&#xff0c;防止接口被恶意打击&#xff08;短时间内大量请求&#xff09;。 比如要求某接口在1分钟内请求次数不超过1000次&#xff0c;那么应该如何设计代码呢&#xff1f; 下面讲两种思路&#xff0c;如果想看代码可…