WangEditor快速实现版

news2025/3/13 6:43:33

WangEditor快速实现版

效果
在这里插入图片描述

案例代码

后端

package com.diy.springboot.controller;

import cn.hutool.core.util.IdUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiImplicitParam;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "富文本编辑器文件上传接口")
@RestController
@RequestMapping("/editor")
public class WangEditorUploadController {

    @Value("${files.upload.path}")
    private String fileUploadPath;

    @ApiOperation(value = "上传图片或视频", notes = "支持图片(jpg,jpeg,png,gif,bmp)和视频(mp4,avi,mkv,mov)格式")
    @ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile")
    @PostMapping("/upload")
    public ResponseEntity<Map<String, Object>> upload(@RequestParam MultipartFile file) {
        if (file.isEmpty()) {
            return ResponseEntity.badRequest().body(createErrorResponse());
        }

        String originalFilename = file.getOriginalFilename();
        String fileType = getFileType(originalFilename);
        if ("other".equals(fileType)) {
            return ResponseEntity.badRequest().body(createErrorResponse());
        }

        try {
            String fileUUID = IdUtil.fastSimpleUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
            File uploadFile = new File(fileUploadPath + fileUUID);

            File parentFile = uploadFile.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }

            file.transferTo(uploadFile);
            return ResponseEntity.ok(createImageResponse(fileUUID));
        } catch (IOException e) {
            return ResponseEntity.badRequest().body(createErrorResponse());
        }
    }

    @ApiOperation(value = "获取文件类型", hidden = true)
    private String getFileType(String filename) {
        String ext = filename.substring(filename.lastIndexOf(".")).toLowerCase();
        switch (ext) {
            case ".jpg":
            case ".jpeg":
            case ".png":
            case ".gif":
            case ".bmp":
                return "image";
            case ".mp4":
            case ".avi":
            case ".mkv":
            case ".mov":
                return "video";
            default:
                return "other";
        }
    }

    @ApiOperation(value = "创建错误响应", hidden = true)
    private Map<String, Object> createErrorResponse() {
        Map<String, Object> response = new HashMap<>();
        response.put("errno", 1);
        response.put("data", Collections.emptyMap());
        return response;
    }

    @ApiOperation(value = "创建图片响应", hidden = true)
    private Map<String, Object> createImageResponse(String filename) {
        Map<String, Object> response = new HashMap<>();
        response.put("errno", 0);

        Map<String, String> imageData = new HashMap<>();
        imageData.put("url", "http://localhost:9090/file/" + filename);
        response.put("data", imageData);

        return response;
    }
}

前端

<template>
  <div id="app">
    <h1>富文本编辑器与HTML渲染</h1>
    <el-row>
      <el-button type="primary" @click="logEditorContent">输出编辑器内容</el-button>
      <el-button type="success" @click="loadSampleContent">回显内容</el-button>
      <el-button type="warning" @click="renderUnsafeHtml">渲染HTML(XSS演示)</el-button>
    </el-row>
    <el-divider></el-divider>
    <div ref="editorContainer" style="border: 1px solid #ccc;"></div>
    <el-divider></el-divider>
    <h2>渲染的HTML内容:</h2>
    <div v-html="renderedContent"></div>
  </div>
</template>

<script>
import E from 'wangeditor'

export default {
  name: 'App',
  data() {
    return {
      editor: null,
      renderedContent: '',
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.editor = new E(this.$refs.editorContainer)

      // 配置图片上传的服务器接口
      this.editor.config.uploadImgServer = 'http://localhost:9090/editor/upload';
      this.editor.config.uploadFileName = 'file';

      // 配置视频上传的服务器接口
      this.editor.config.uploadVideoServer = 'http://localhost:9090/editor/upload';
      this.editor.config.uploadVideoName = 'file';

      this.editor.highlight = window.hljs;

      // 修改图片上传的回调处理逻辑,适配后端返回的数据结构
      this.editor.config.uploadImgHooks = {
        customInsert: (insertImgFn, result) => {
          if (result.errno === 0 && result.data && result.data.url) {
            // 直接使用data.url,不再假设data是数组
            insertImgFn(result.data.url);
          } else {
            console.error('图片上传失败', result);
          }
        },
      };

      // 视频上传的回调处理逻辑
      this.editor.config.uploadVideoHooks = {
        customInsert: (insertVideoFn, result) => {
          if (result.errno === 0 && result.data && result.data.url) {
            insertVideoFn(result.data.url);
          } else {
            console.error('视频上传失败', result);
          }
        },
      };

      this.editor.create()
    })
  },
  beforeDestroy() {
    if (this.editor) {
      this.editor.destroy()
    }
  },
  methods: {
    logEditorContent() {
      if (this.editor) {
        const content = this.editor.txt.html()
        console.log("编辑器内容:", content)
        this.renderedContent = content
      }
    },
    loadSampleContent() {
      if (this.editor) {
        const sampleContent = `
          <h2>欢迎使用 WangEditor</h2>
          <p>这是一个<strong>富文本编辑器</strong>示例。</p>
          <ul>
            <li>支持多种格式</li>
            <li>易于使用</li>
            <li>功能强大</li>
          </ul>
          <p>你可以在这里添加<span style="color: blue;">各种样式</span>的文本。</p>
          <blockquote>这是一个引用示例。</blockquote>
        `
        this.editor.txt.html(sampleContent)
        this.renderedContent = sampleContent
      }
    },
    renderUnsafeHtml() {
      const unsafeHtml = '<img src="x" onerror="alert(\'XSS 攻击演示\')">'
      this.editor.txt.html(unsafeHtml)
      this.renderedContent = unsafeHtml
    }
  },
}
</script>

<style>
#app {
  width: 80%;
  margin: 20px auto;
}

.w-e-text-container {
  height: 300px !important;
}
</style>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java常见面试技术点整理讲解——后端框架(整理中,未完成)

前言&#xff1a; 对于后端常用框架的技术整理&#xff0c;其实框架在平时就是会用就行&#xff0c;但面试时多半需要描述实现原理&#xff0c;这个要靠自己理解&#xff0c;不推荐死记硬背。 这篇和另外几篇文章区分开&#xff0c;主要用于规整Java后端各种框架&#xff0c;…

Dify 本地部署教程

目录 一、下载安装包 二、修改配置 三、启动容器 四、访问 Dify 五、总结 本篇文章主要记录 Dify 本地部署过程,有问题欢迎交流~ 一、下载安装包 从 Github 仓库下载最新稳定版软件包,点击下载~,当然也可以克隆仓库或者从仓库里直接下载zip源码包。 目前最新版本是V…

Python----数据可视化(Seaborn二:绘图一)

常见方法 barplot方法 单独绘制条形图 catplot方法 可以条形图、散点图、盒图、小提亲图、等 countplot方法 统计数量 一、柱状图 seaborn.barplot(dataNone, xNone, yNone, hueNone, colorNone, paletteNone) 函数描述data用于绘图的数据集。x用于绘制长格式数据的输入。…

加速科技Flex10K-L测试机:以硬核创新重塑显示驱动芯片测试新标杆!

在2024年召开的世界显示产业创新发展大会上&#xff0c;加速科技自主研发的高密度显示驱动芯片测试设备Flex10K-L凭借其突破性技术创新&#xff0c;成功入选"十大创新技术&#xff08;产品&#xff09;"。作为国内显示驱动芯片测试领域的标杆性设备&#xff0c;Flex1…

linux-文本处理命令(echo,cut,sort,uniq,wc,tr,grep)

echo 打印&#xff08;标准输入输出命令&#xff09; [rootlocalhost ~]# echo $HOSTNAME-----$引用变量 localhost [rootlocalhost ~]# echo "$HOSTNAME"----“”弱引用符&#xff08;可以解释特殊含义的字符&#xff09; localhost [rootlocalhost ~]# echo $HOSTN…

spring-boot-starter和spring-boot-starter-web的关联

maven的作用是方便jar包的管理&#xff0c;所以每一个依赖都是对应着相应的一个或者一些jar包&#xff0c;从网上看到很多对spring-boot-starter的描述就是“这是Spring Boot的核心启动器&#xff0c;包含了自动配置、日志和YAML。”没看太明白&#xff0c;所参与的项目上也一直…

群晖DS223 Docker搭建为知笔记

群晖DS223 Docker搭建为知笔记&#xff0c;打造你的专属知识宝库 一、引言 在数字化信息爆炸的时代&#xff0c;笔记软件成为了我们管理知识、记录灵感的得力助手。为知笔记&#xff0c;作为一款专注于工作笔记和团队协作的云笔记产品&#xff0c;以其丰富的功能和便捷的使用体…

NLP文本分析之依存句法分析(理论及技术实践)

引言 在自然语言处理&#xff08;NLP&#xff09;领域中&#xff0c;理解句子的语法结构是实现语义理解的基础。依存句法分析&#xff08;Dependency Parsing&#xff09; 作为句法分析的核心任务之一&#xff0c;通过揭示句子中词语之间的依存关系&#xff0c;为机器翻译、信…

Nginx(基础安装+配置文件)

目录 一.Nginx基础 1.基础知识点 2.异步非阻塞机制 二.Nginx安装 2.1安装nginx3种方式 1.包管理工具安装&#xff08;yum/apt&#xff09; 2.本地包安装&#xff08;rpm/dpkg&#xff09; 3.源码编译安装 3.1 源码编译安装nginx流程&#xff08;ubuntu&#xff09; 1.…

uni-app+vue3学习随笔

目录相关 static文件 编译器会把static目录中的内容整体复制到最终编译包内&#xff0c; 非 static 目录下的文件&#xff08;vue组件、js、css 等&#xff09;只有被引用时&#xff0c;才会被打包编译。 css、less/scss 等资源不要放在 static 目录下&#xff0c;建议这些…

prompt大师高效提示词解析

Prompt大师李继刚高效提示词示例解析 一、「汉语新解」提示词 核心结构 采用Lisp语言框架嵌套中文语义&#xff0c;通过(defun 新汉语老师 ()...)定义角色风格&#xff08;融合奥斯卡王尔德、鲁迅的批判性语言&#xff09;&#xff0c;用(隐喻 (一针见血...))构建解释逻辑链。…

QT系列教程(18) MVC结构之QItemSelectionModel模型介绍

视频教程 https://www.bilibili.com/video/BV1FP4y1z75U/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 QItemSelectionModel Qt的MVC结构支持多个View共享同一个model&#xff0c;包括该model的选中状态等。我们可以通过设置QItemSelectionModel&#xff0c;来更改View的选…

【Java面试题汇总】Java面试100道最新合集!

1.说说你对面向对象的理解 得分点 封装,继承,多态、概念、实现方式和优缺点 面向对象的三大基本特征是&#xff1a;封装、继承、多态。 封装&#xff1a;将对象的状态和行为包装在一个类中并对外界隐藏实现的细节&#xff0c;可以通过访问修饰符控制成员的访问权限&#xff0c…

Vue 实现智能检测文字是否溢出,溢出显示省略号,鼠标悬浮显示全部【附封装组件完整代码+详细注释+粘贴即食】

一、场景需求 在项目中&#xff0c;经常会遇到文本内容超出容器的情况。为了提高用户体验&#xff0c;我希望在文字溢出时显示悬浮提示&#xff0c;未溢出时则不显示。 二、效果演示 三、实现原理 DOM宽度对比法&#xff1a;通过比较元素的scrollWidth&#xff08;实际内容宽…

51c大模型~合集10

我自己的原文哦~ https://blog.51cto.com/whaosoft/11547799 #Llama 3.1 美国太平洋时间 7 月 23 日&#xff0c;Meta 公司发布了其最新的 AI 模型 Llama 3.1&#xff0c;这是一个里程碑时刻。Llama 3.1 的发布让我们看到了开源 LLM 有与闭源 LLM 一较高下的能力。 Meta …

关于C/C++语言的初学者在哪刷题,怎么刷题

引言&#xff1a; 这篇博客主要是针对初学者关于怎么在网上刷题&#xff0c;以及在哪里刷题。 1.介绍平台&#xff08;在哪刷题&#xff09;&#xff1a; 1.牛客牛客网https://www.nowcoder.com/ &#xff1a;有许多面试题&#xff0c;也有许多供学习者练习的题 2.洛谷洛谷 …

AI自动化编程初探

先说vscodeclinemodelscope方案&#xff0c;后面体验trae或者cursor再写写其它的。vscode和trae方案目前来说是免费的&#xff0c;cursor要用claud需要付费&#xff0c;而且不便宜&#xff0c;当然效果可能是最好的。 vscode方案&#xff0c;我的经验是最好在ubuntu上&#xff…

《人月神话》:软件工程的成本寓言与生存法则

1975年&#xff0c;Fred Brooks在《人月神话》中写下那句振聋发聩的断言——“向进度落后的项目增加人力&#xff0c;只会让进度更加落后”——时&#xff0c;他或许未曾料到&#xff0c;这一观点会在半个世纪后的人工智能与云原生时代&#xff0c;依然如达摩克利斯之剑般悬在每…

深入理解Java中的static关键字及其内存原理

static是Java中实现类级共享资源的核心修饰符&#xff0c;它突破了对象实例化的限制&#xff0c;使得变量和方法能够直接与类本身绑定。这种特性让static成为构建工具类、全局配置等场景的利器&#xff0c;但同时也带来独特的内存管理机制需要开发者关注。 static修饰成员变量…

20250310-组件基础2

通过插槽来分配内容 一些情况下我们会希望能和 HTML 元素一样向组件中传递内容&#xff1a; <AlertBox>传入的内容 </AlertBox> 我们期望能渲染成这样&#xff1a; 这可以通过 Vue 的自定义 <slot> 元素来实现&#xff1a; <template><div clas…