秀米编辑器(xiumi)+百度编辑器(Ueditor) 集成 :解决集成问题,秀米编辑器导出到百度编辑器格式问题,图片保存到自己的服务器(阿里云OSS)

news2024/11/25 12:57:22

1.集成前提条件:

        1. 需要集成百度编辑器到环境中

        2.https环境下才可以导出数据到百度编辑器,如果不是https环境,会出现错误

        

然后我们开始讲解如何集成:


2.引入资源:


//百度编辑器需要修改的文件(配置与原始的配置不一样,后面会详细讲)
<script type="text/javascript" src="/static/lib/ueditor1_4_3_3-utf8-php/utf8-php-xiumi/ueditor.config.js?t=1"></script>
<script type="text/javascript" src="/static/lib/ueditor1_4_3_3-utf8-php/utf8-php-xiumi/ueditor.all.min.js"></script>
//秀米编辑器的JS,这个需要下载(下载可以去xiumi.us下载,也可以参考博主提供的相关代码)
<script type="text/javascript" src="/static/lib/ueditor1_4_3_3-utf8-php/utf8-php-xiumi/xiumi-ue-dialog-v5.js"></script>


3.初始化百度编辑器:


<script>
    var ue = UE.getEditor('editor');
</script>

//xiumi-ue-dialog-v5.js可以去官网下载,也可以直接使用博主提供的相关代码
UE.registerUI('dialog', function (editor, uiName) {
    var btn = new UE.ui.Button({
        name   : 'xiumi-connect',
        title  : '秀米',
        onclick: function () {
            var dialog = new UE.ui.Dialog({
                iframeUrl: '相对地址/XIUMI connect.html',//这个参数中的html需要下载或者使用博主提供的代码(后面会贴出代码)
                editor   : editor,
                name     : 'xiumi-connect',//打开页面指定名字
                title    : "秀米编辑器",//打开页面指定标题
                cssRules : "width: " + (window.innerWidth - 60) + "px;" + "height: " + (window.innerHeight - 60) + "px;",//打开页面大小配置
            });
            dialog.render();
            dialog.open();
        }
    });

    return btn;
});


//XIUMI connect.html可以去官网下载,也可以直接使用博主提供的相关代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>XIUMI connect</title>
    <style>
        html, body {padding: 0;margin: 0;}
        #xiumi {position: absolute;width: 100%;height: 100%;border: none;box-sizing: border-box;}
    </style>
</head>
<body>
<!--引入秀米页面-->
<iframe id="xiumi" src="//xiumi.us/studio/v5#/paper"></iframe>
<!--引入秀米页面-->
<script type="text/javascript" src="./internal.js"></script>
<script>
    var xiumi = document.getElementById('xiumi');
    var xiumi_url = window.location.protocol + "//xiumi.us";
    xiumi.onload = function () {xiumi.contentWindow.postMessage('ready', xiumi_url);};
    document.addEventListener("mousewheel", function (event) {event.preventDefault();event.stopPropagation();});
    window.addEventListener('message', function (event) {
        if (event.origin == xiumi_url) {
            editor.execCommand('insertHtml', event.data);
            editor.fireEvent("catchRemoteImage");//这个配置一定写,catchRemoteImage表示自定义上传方法名(注意:秀米编辑器导入百度编辑器的时候,图片文件不会自动上传到我们自己设置服务器,所以这一点一定要写上)
            dialog.close();
        }
    }, false);
</script>
</body>
</html>

4.ueditor.config.js配置修改:

        //开启配置(去掉注释),开启这个配置的作用:秀米编辑器数据导入百度编辑器图片样式会错乱,所以需要配置:iframeCssUrl: URL + '/themes/iframe.css'


        //开启配置(去掉注释),开启这个配置的作用:设置是否抓取远程图片(Ctrl+c和Ctrl+v会触发远程获取图片并上传到自己服务器事件):catchRemoteImageEnable: true 


        //修改配置:section[] 修改为 section:['class', 'style'],(作用是过滤器:秀米编辑器导入百度编辑器的过程中,class和style不被过滤,各种样式得以保存)
section:['class', 'style'],

        //iframe.css:添加自己自定义样式(存放相对地址:ueditor/themes/iframe.css),这个需要自己重写,代码参考博主提供的demo


img {
    max-width: 100%;
}
body {
    overflow-y: scroll !important;
}
.view {
    word-break: break-all;
}
.vote_area {
    display: block;
}
.vote_iframe {
    background-color: transparent;
    border: 0 none;
    height: 100%;
}
#edui1_imagescale{display:none !important;}

//传到自己服务器的上传方法(PHP版),主要由两个文件(存储地址:ueditor/php):Uploader.class.php  和  config.json

        //先讲Uploader.class.php文件(主要是引入OSS上传方法,集成OSS方法就不赘述了,可以参考阿里云

<?php

//阿里云OSS上传自动加载文件(注意相对地址
require_once realpath(dirname(__FILE__).'/../../../../../applicaction/libraries/aliyun-oss/autoload.php');
use OSS\OssClient;
use OSS\Core\OssException;

class Uploader
{
    private $fileField; //文件域名
    private $file; //文件上传对象
    private $base64; //文件上传对象
    private $config; //配置信息
    private $oriName; //原始文件名
    private $fileName; //新文件名
    private $fullName; //完整文件名,即从当前配置目录开始的URL
    private $filePath; //完整文件名,即从当前配置目录开始的URL
    private $fileSize; //文件大小
    private $fileType; //文件类型
    private $stateInfo; //上传状态信息,
    private $stateMap = array( //上传状态映射表,国际化用户需考虑此处数据的国际化
        "SUCCESS",
        "文件大小超出 upload_max_filesize 限制",
        "文件大小超出 MAX_FILE_SIZE 限制",
        "文件未被完整上传",
        "没有文件被上传",
        "上传文件为空",
        "ERROR_TMP_FILE" => "临时文件错误",
        "ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件",
        "ERROR_SIZE_EXCEED" => "文件大小超出网站限制",
        "ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许",
        "ERROR_CREATE_DIR" => "目录创建失败",
        "ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限",
        "ERROR_FILE_MOVE" => "文件保存时出错",
        "ERROR_FILE_NOT_FOUND" => "找不到上传文件",
        "ERROR_WRITE_CONTENT" => "写入文件内容错误",
        "ERROR_UNKNOWN" => "未知错误",
        "ERROR_DEAD_LINK" => "链接不可用",
        "ERROR_HTTP_LINK" => "链接不是http链接",
        "ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确",
        "INVALID_URL" => "非法 URL",
        "INVALID_IP" => "非法 IP"
    );

    /**
     * 构造函数
     */
    public function __construct($fileField, $config, $type = "upload")
    {
        $this->fileField = $fileField;
        $this->config = $config;
        $this->type = $type;
        if ($type == "remote") {
            $this->saveRemote();
        } else if($type == "base64") {
            $this->upBase64();
        } else {
            $this->upFile();
        }

        $this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = iconv('unicode', 'utf-8', $this->stateMap['ERROR_TYPE_NOT_ALLOWED']);
                
                //The AccessKeyId from OSS or STS
                $this->accessKeyId="";
                //The AccessKeySecret from OSS or STS
                $this->accessKeySecret="";
                //The domain name of the datacenter,For example: oss-cn-hangzhou.aliyuncs.com
                $this->endpoint="";
    }

    /**
     * 上传文件的主处理方法(这个需要替换原有的方法)
     */
    private function upFile()
    {
        $file = $this->file = $_FILES[$this->fileField];
        if (!$file) {
            $this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND");
            return;
        }
        if ($this->file['error']) {
            $this->stateInfo = $this->getStateInfo($file['error']);
            return;
        } else if (!file_exists($file['tmp_name'])) {
            $this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND");
            return;
        } else if (!is_uploaded_file($file['tmp_name'])) {
            $this->stateInfo = $this->getStateInfo("ERROR_TMPFILE");
            return;
        }
        //修改:上传阿里云OSS(file:表示存储地址)
        $ossClient=new OssClient($this->accessKeyId,$this->accessKeySecret,$this->endpoint);
        $ossClient->uploadFile('ine', 'file/'.date ('Ym') .'/'.$file['name'], $file['tmp_name']);
        $this->oriName = $file['name'];
        $this->fileSize = $file['size'];
        $this->fileType = $this->getFileExt();
        $this->fullName = $this->getFullName();
        $this->filePath = $this->getFilePath();
        $this->fileName = $this->getFileName();
        $dirname = dirname($this->filePath);

        //检查文件大小是否超出限制
        if (!$this->checkSize()) {
            $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
            return;
        }

        //检查是否不允许的文件格式
        if (!$this->checkType()) {
            $this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED");
            return;
        }

        $this->stateInfo = $this->stateMap[0];
    }
 
    /**
     * 拉取远程图片(这个需要替换原有的方法)
     */
    private function saveRemote()
    {
        $imgUrl = htmlspecialchars($this->fileField);
        $imgUrl = str_replace("&amp;", "&", $imgUrl);

        //http开头验证
        if (strpos($imgUrl, "http") !== 0) {
            $this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
            return;
        }

        preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);
        $host_with_protocol = count($matches) > 1 ? $matches[1] : '';

        // 判断是否是合法 url
        if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
            $this->stateInfo = $this->getStateInfo("INVALID_URL");
            return;
        }

        preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
        $host_without_protocol = count($matches) > 1 ? $matches[1] : '';

        // 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
        $ip = gethostbyname($host_without_protocol);
        // 判断是否是私有 ip
        if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
            $this->stateInfo = $this->getStateInfo("INVALID_IP");
            return;
        }

        //获取请求头并检测死链
        $heads = get_headers($imgUrl, 1);
        if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
            $this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
            return;
        }
        //格式验证(扩展名验证和Content-Type验证)
        $fileType = strtolower(strrchr($imgUrl, '.'));
        if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) {
            $this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
            return;
        }

        //打开输出缓冲区并获取远程图片
        ob_start();
        $context = stream_context_create(
            array('http' => array('follow_location' => false))
        );
        readfile($imgUrl, false, $context);
        $img = ob_get_contents();
        ob_end_clean();
        preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
        $this->oriName = $m ? $m[1]:"";
        $this->fileSize = strlen($img);
        $this->fileType = $this->getFileExt();
        $this->fullName = $this->getFullName();
        $this->filePath = $this->getFilePath();
        $this->fileName = $this->getFileName();
        $dirname = dirname($this->filePath);

        //检查文件大小是否超出限制
        if (!$this->checkSize()) {
            $this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
            return;
        }
        $this->stateInfo = $this->stateMap[0];
    }

 
    /**
     * 获取文件完整路径(这个需要替换原有的方法)
     */
    private function getFilePath()
    {
        $fullname = $this->fullName;
        return $fullname;
    }
}
 


5.config.json配置修改:
        

    /* 上传图片配置项 */
    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
    "imageFieldName": "upfile", /* 提交的图片表单名称 */
    "imageMaxSize": 2048000, /* 上传大小限制,单位B */
    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageUrlPrefix": "https://oss-cn-shanghai.aliyuncs.com", /* 这个需要自己替换 */
    "imagePathFormat": "/file/{yyyy}{mm}/{filename}", /* 上传保存路径*/
        
        
    "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
    "catcherPathFormat": "/file/{yyyy}{mm}/{filename}", /* 上传保存路径 */
    "catcherUrlPrefix": "https://oss-cn-shanghai.aliyuncs.com", /* 这个需要自己替换 */
    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */

到此为止,前面所提的集成问题和图片上传问题就解决完成了


        秀米编辑器(xiumi)+百度编辑器(Ueditor) 集成 已经完成:

        秀米编辑器导出到百度编辑器格式问题,图片保存到自己的服务器(阿里云OSS)

示例截图

 

  

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

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

相关文章

测试入门第一步------编写接口测试用例

自动化始终只是辅助测试工作的一个手段&#xff0c;对于测试人员而言&#xff0c;测试基础和测试用例的设计才是核心。如果测试用例的覆盖率或者质量不高&#xff0c;那将这部分用例实现为自动化用例的意义也就不大了。 那么&#xff0c;接口测试用例应该怎么编写呢&#xff1…

Spring boot集成RabbitMq

Spring boot集成RabbitMq 一、搭建RabbitMq1.1 参考1.2 配置erlong的环境变量1.3 RabbitMQ对应的在注册表中的位置 二、使用教程2.1 打开服务端2.2 注意的问题2.3 Queue的包 三、git命令3.1 git remote3.2 git remote add origin "xxxx"3.3 git push -u origin maste…

使用esp32+micropython+microdot搭建web(http+websocket)服务器(超详细)第一部分

使用esp32micropythonmicrodot搭建web(httpwebsocket)服务器&#xff08;超详细&#xff09;第一部分 microdot文档速查 什么是Microdot?Microdot是一个可以在micropython中搭建物联网web服务器的框架micropyton文档api速查 Quick reference for the ESP32 先来个小demo先体…

数据仓库——原理+实战(一)

一、数据仓库概述 1. 数据仓库诞生原因 &#xff08;1&#xff09;历史数据积存&#xff08;存放在线上业务数据库中&#xff0c;当数据积压到一定程度会导致性能下降&#xff0c;所以需要将实用频率低的冷数据转移到数据仓库中&#xff09; &#xff08;2&#xff09;企业数…

【C++11】线程库

文章目录 1. get_idthis_thread 2. 锁1. 为什么要使用锁&#xff1f;2. 锁的使用并行 与 串行递归锁 recursive_mutextimed_mutexlock_guard 与 unique_lock 3. atomic4. 条件变量线程等待线程唤醒条件变量的应用问题1&#xff1a;如何保证 v1先运行&#xff0c;v2阻塞&#xf…

python的tqdm一些操作

主要参数 iterable: 可迭代的对象, 在手动更新时不需要进行设置 desc: str, 左边进度条的描述性文字 total: 总的项目数 leave: bool, 执行完成后是否保留进度条 file: 输出指向位置, 默认是终端, 一般不需要设置 ncols: 调整进度条宽度, 默认是根据环境自动调节长度, 如果设置…

VUE 2X 事件处理 ⑤

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs E v e n t j s Eventjs Eventjs总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ ⡖⠒⠒⠒⠤⢄⠀⠀⠀…

MySQL面试题--聚簇索引,非聚簇索引,回表查询

目录 概念 聚集索引选取规则: 面试回答 大纲 回答 概念 分类 含义 特点 聚集索引(Clustered Index) 将数据存储与索引放到了一块&#xff0c;索引结构的叶子节点保存了行数据 必须有,而且只有一个 二级索引(Secondary Index) 将数据与索引分开存储&#xff0c;索引…

进程的引入(操作系统)

目录 1、进程的概念 2、进程状态及状态转换 &#xff08;1&#xff09;进程的状态 &#xff08;2&#xff09;状态的转换 3、进程控制块&#xff08;PCB&#xff09; 4、进程的组成和上下文 5、进程的队列 6、进程的类型和特征 7、进程间相互联系与相互作用 8、进程的…

pcl1.12.1重新安装boost库

因为我的库有问题&#xff0c;直接使用pcl1.12.1的时候报错&#xff0c;于是重新安装boost库 1.78.0地址(因为打开pcl1.12.1的安装目录&#xff0c;发现boost库是1.78.0&#xff0c;所以去官网找到对应的版本进行安装) Index of main/release/1.78.0/sourcehttps://boostorg.j…

OpenHarmony端云一体化应用开发快速入门练习(中)登录认证

一、登录认证手机 可以在应用中集成手机帐号认证方式&#xff0c;您的用户可以使用“手机号码密码”或者“手机号码验证码”的方式来登录您的应用。 &#xff08;一&#xff09;前提条件 需要在AGC控制台开通认证服务。 需要先在您的应用中集成SDK。 &#xff08;二&#xff…

安全测试-优秀测试工程师必备的4项安全测试方法

用您5分钟时间阅读完&#xff0c;希望能对您有帮助&#xff01; 一.安全性测试 1、安全性测试方法 测试手段可以进行安全性测试&#xff0c;目前主要安全测试方法有&#xff1a;   1&#xff09;静态的代码安全测试 主要通过对源代码进行安全扫描&#xff0c;根据程序中数…

网站开发实录(四)个人博客建站

一、前期准备 由于时间问题&#xff0c;已经准备好了服务器以及域名 服务器平台为“雨云”&#xff08;朋友那里嫖来的&#xff09;&#xff0c;域名购买平台为阿里云&#xff08;零元购来的&#xff09;。接下来我将以此为例介绍个人博客建站过程&#xff0c;顺带记录我的第二…

原生微信小程序全流程(基础知识+项目全流程)

小程序的基本使用 小程序文件类型 小程序主要提供了 4 种文件类型&#xff1a; 类型名称作用是否必须存在.wxml用于页面的布局结构&#xff0c;相当于网页中 .html 文件是.wxss用于页面的样式&#xff0c;相当于网页中的 .css 文件否.js用于页面的逻辑是.json用于页面的配置…

最新Python3.11.4版本和PyCharm开发工具安装详细教程

Python3.11.4版本安装详细教程 1. 官网下载Python安装包1.1 进入官网1.2 查看系统类型1.3 选择与主机位数相同的安装程序 2.运行安装程序2.1 Customize installation&#xff08;自定义安装&#xff09;2.2 Optional Features&#xff08;可选功能&#xff09;2.3 Advanced Opt…

synchronized 底层实现原理、重量级锁、轻量锁、锁膨胀、锁自旋、偏向锁详解

目录 0、基础知识&#xff1a;Java对象的存储格式 1. synchronized底层&#xff1a;Monitor&#xff08;重量级锁&#xff09;&#xff1a;被锁的对象与Monitor的关系 2. synchronized底层&#xff1a;轻量级锁优化&#xff0c;栈帧与被锁的对象的关系 3. 锁膨胀&#xff…

【arduino】HC-SR04超声波测距模块的驱动与使用

arduino超声波测距模块的驱动与使用 什么是超声波测距模块参数:引脚定义电路超声波传感器的控制时序驱动代码接线代码工程文件超声波是振动频率高于20KHZ的机械波。它具有频率高、波长短、绕射现象小、方向性好、能够成为射线而定向传播等特点应用广泛,适合大学生、工程师、技…

精简版Git基础操作(快速上手)

文章目录 前言一、初始化二、新建仓库三、工作区域和文件状态四、添加和提交文件五、回退到之前版本六、查看文件差异七、从版本库中删除文件八、.gitignore忽略文件九、github远程仓库--SSH配置和克隆仓库十、关联本地仓库与远程仓库十一、分支十二、解决合并冲突回退和rebase…

Go mmap 文件内存映射

Go mmap 文件内存映射 mmap是个很好用的内存映射工具&#xff0c;它可以将文件映射到内存中&#xff0c;可以方便地操作文件。使用mmap的优点是&#xff1a; 内存映射可以使得读写文件的性能更高&#xff0c;因为操作的是内存而不是磁盘。可以方便地操作文件&#xff0c;不需…

语音录音转文字的方法使用过吗

大家好&#xff01;今天我要给你们介绍一个实用的功能&#xff0c;那就是录音转文字啦&#xff01;它可以把录音中的声音内容快速且准确地转换成文字格式&#xff0c;让我们在工作和学习中变得更加高效和便利。我们在会议记录、采访访谈、语音笔记等领域&#xff0c;可以很大地…