开了网站建设公司 如何接业务,建设银行网站打不开别的网站可以,高明顺德网站建设,投放广告赚钱平台有哪些CKEditor5 经验总结 背景CKEditor5 简介使用基础初始化定义HTML实例自定义图片上传适配器开启图片上传图片上传遇到的问题 开启视频上传视频上传遇到的问题 参考博客 背景
项目中 CKEditor4 更新到 CKEditor5(CKEditor4 不支持视频#xff0c;除升级版本外也可以通过安装插件… CKEditor5 经验总结 背景CKEditor5 简介使用基础初始化定义HTML实例自定义图片上传适配器开启图片上传图片上传遇到的问题 开启视频上传视频上传遇到的问题 参考博客 背景
项目中 CKEditor4 更新到 CKEditor5(CKEditor4 不支持视频除升级版本外也可以通过安装插件的方式实现点击这里)两个版本间的变化很大且 CKEditor5 没有对应的中文文档以及相关资料较少。 最终通过 CKEditor5 实现富文本的图片、视频上传功能。 本文以 Classic editor 经典编辑器为例记录在使用过程中遇到的问题。
CKEditor5 简介
CKEditor 5是一个超现代的JavaScript富文本编辑器具有MVC架构、自定义数据模型和虚拟DOM。它是在ES6中从头编写的并且有出色的webpack支持。包含经典编辑器、内联编辑器、气球编辑器、气球块编辑器、文档编辑器。 官方提供了四种引入方式
CDNnpmOnline builderZip download
使用
基础初始化
scriptClassicEditor.create( document.querySelector( #editor ) ).catch( error {console.error( error );} );
/script定义HTML
script srchttps://cdn.ckeditor.com/ckeditor5/16.0.0/classic/ckeditor.js/script
script srchttps://cdn.ckeditor.com/ckeditor5/16.0.0/classic/translations/zh-cn.js/scriptform idthisForm classform-horizontaldiv classrowdiv classform-groupdiv classcol-xs-12textarea idadContent/textarea/div/div/div
/form实例
script typetext/javascript
// 初始化内容富文本
var thisAdEditor;
$(function() {ClassicEditor.create(document.querySelector(#adContent), {language: zh-cn, // 中文extraPlugins: [ MyCustomUploadAdapterPlugin ], // 参考官方文档自定义Adapter实现图片上传mediaEmbed: { // 提供视频上传支持previewsInData: true,providers: [{name: mediaUpload,url: [ // 正则表达式根据实际情况修改/^test01\.bintech\.com\/upload\/(\w)/,/^http:\/\/(\w)/,],html: match {//获取媒体urlconst input match[input];return (div styleposition: relative; padding-bottom: 100%; height: 0; padding-bottom: 56.2493%; iframe srchttp://${input} styleposition: absolute; width: 100%; height: 100%; top: 0; left: 0; frameborder0 allowautoplay; encrypted-media allowfullscreen /iframe /div);}}]}}).then(editor {thisAdEditor editor;}).catch(error {console.error(error);});
});
/script自定义图片上传适配器
官方文档参考https://ckeditor.com/docs/ckeditor5/latest/framework/deep-dive/upload-adapter.html
script
class MyUploadAdapter {constructor( loader ) {// 上载期间要使用的文件加载器实例this.loader loader;}// 启动上传过程upload() {return this.loader.file.then( file new Promise( ( resolve, reject ) {this._initRequest();this._initListeners( resolve, reject, file );this._sendRequest( file );} ) );}// 中止上传过程abort() {if ( this.xhr ) {this.xhr.abort();}}// 初始化 XMLHttpRequest 对象使用URL传递给构造函数_initRequest() {const xhr this.xhr new XMLHttpRequest();// *使用JSON作为数据结构的POST请求,url根据实际情况配置xhr.open( POST, admin/upload/rest/files, true );xhr.responseType json;}// 初始化XMLHttpRequest监听器_initListeners( resolve, reject, file ) {const xhr this.xhr;const loader this.loader;const genericErrorText 无法上传文件: ${ file.name }.;xhr.addEventListener( error, () reject( genericErrorText ) );xhr.addEventListener( abort, () reject() );xhr.addEventListener( load, () {const response xhr.response;// 当响应上传失败时调用reject()函数if ( !response || response.error ) {return reject( response response.error ? response.error.message : genericErrorText );}// 上传成功的处理resolve( {default: response.url} );} );// 编辑器用户界面中显示上传进度条if ( xhr.upload ) {xhr.upload.addEventListener( progress, evt {if ( evt.lengthComputable ) {loader.uploadTotal evt.total;loader.uploaded evt.loaded;}} );}}// 准备数据并发送请求_sendRequest( file ) {// 准备表单数据const data new FormData();data.append( uploadFiles, file );// 实现认证和CSRF保护等安全机制// 发送请求.this.xhr.send( data );}
}function MyCustomUploadAdapterPlugin( editor ) {editor.plugins.get( FileRepository ).createUploadAdapter ( loader ) {// 配置上传脚本的后端URLreturn new MyUploadAdapter( loader );};
}
/script开启图片上传
初始化内容富文本时引入自定义上传AdapterextraPlugins: [ MyCustomUploadAdapterPlugin ]。 官方文档提供两种图片上传方案Official upload adapters 和 Custom upload adapters 区别在于前者功能更强大但需要付费订阅参考地址官方文档参考
图片上传遇到的问题
a、无法上传图片 场景描述 控制台提示filerepository-no-upload-adapter 原因 未定义图片上传适配器 解决方案 参考官方文档自定义图片上传适配器并在初始化ClassicEditor插件时配置自定义图片上传适配器MyCustomUploadAdapterPlugin官方文档参考 b、403异常 场景描述 初始化ClassicEditor并配置自定义图片上传适配器上传图片时提示控制台403异常 原因 未放开CSRF校验 解决方案 在Security配置文件中加如下代码放开请求路径的CSRF保护等安全机制以避免出现403错误。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.http.HttpServletRequest;EnableWebSecurity
Configuration
EnableGlobalMethodSecurity(prePostEnabled true)
public class Security extends WebSecurityConfigurerAdapter {Autowiredprivate AuthenticationDetailsSourceHttpServletRequest, WebAuthenticationDetails authenticationDetailsSource;Autowiredprivate AuthenticationProvider authenticationProvider;Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().ignoringAntMatchers(/upload/**).and().headers().frameOptions().sameOrigin().xssProtection().block(true).and();... // 其他配置}
}c、需要注意的细节
图片上传URL根据实际情况修改xhr.open( ‘POST’, ‘admin/upload/rest/files’, true )Controller在定义时RequestParam(“uploadFiles”) 要与 data.append( ‘uploadFiles’, file );一致。
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
RestController
public class UploadRestController {Autowiredprivate UploadService uploadService;RequestMapping(value /admin/upload/rest/files, method RequestMethod.POST)public JSON uploadFiles(RequestParam(uploadFiles) MultipartFile file, HttpServletRequest request,HttpServletResponse response)throws IOException {return uploadService.uploadFiles(request, response, file);}
}请求返回值格式
成功
{uploaded:true,url:图片地址(如/upload/xxx/abc.jpg)
}失败
{uploaded:false, url:
}开启视频上传
视频上传遇到的问题
a. 视频部分引入媒体url失败 场景描述 点击工具栏中的视频选项随便引入一个媒体url提示不支持该媒体url; 原因 目前CKEditor5支持的视频provider仅有dailymotion、spotify、youtube、vimeo、instagram、twitter、googleMaps、flickr和facebook每个provider都有自己的媒体url匹配路径 具体可查看meida-embed原文档; 解决方案 自定义视频provider 在原有js部分中的初始化加入自定义的provider在url属性中定义自己的url匹配规则详见上文。 b. 视频预览及页面不显示视频问题 场景描述 在富文本框贴入视频链接后视频不能显示 原因 当视频链接贴入富文本筐后插件会自动生成一个如下标签
figure classmedia ck-widget ck-widget_selected contenteditablefalsediv classck-media__wrapper data-oembed-url视频访问路径.../div...
/figure解决方案 H5 标签
scriptdocument.querySelectorAll(dev[data-oembed-url]).forEach( element {const videoLable document.createElement(video);videoLable.setAttribute(src, element.getAttribute(data-oembed-url));videoLable.setAttribute(controls, controls);videoLable.setAttribute(style, width: 100%; height: 100%;);element.appendChild(videoLable);});
/script参考博客
https://blog.csdn.net/oldpubcat/article/details/105518980 https://blog.csdn.net/huhui806/article/details/105312410