☰
CKEditor 4 拖放图片自动转为 Base64:`clipboard_handleImages` 机制与手动测试用例深度解析
2026/10/15 2:56:24 网站建设 项目流程
  • 前端
  • UI组件

【免费下载链接】ckeditor4

The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.

项目地址:https://gitcode.com/gh_mirrors/ck/ckeditor4
点击查看免费下载

导读

本文围绕 CKEditor 4 仓库中位于tests/plugins/clipboard/manual/draganddropimage.md的手动测试用例,系统讲解自 4.17.0 起引入的"拖放图片自动转 Base64"能力(对应 issue #4681):将 PNG/JPEG/GIF 图片从文件系统拖入编辑器后,clipboard 插件会通过FileReader把图片读取为data:image/...;base64,...并插入<img>标签;而 PDF 等不支持的类型则被静默忽略并弹出通知。读完本文你将掌握该功能的验证方法、底层事件与转换链路、相关配置项(clipboard_handleImages、clipboard_notificationDuration)以及配套自动测试的断言细节。

一、测试用例要验证什么:拖放图片的两种场景

该手动测试文档通过两个场景,分别验证"支持的类型被正确转换"与"不支持的类型被正确拒绝"两条行为路径,且同时覆盖经典(wysiwygarea)与行内(inline)两种编辑器形态。

测试前置标签声明了所需插件集合:wysiwygarea, sourcearea, clipboard, undo, image, floatingspace,其中clipboard是本功能的核心承载插件,image用于保证<img>在内容中被合法解析与显示。

Scenario 1:拖放受支持的图片格式

操作步骤:

  1. 打开浏览器控制台(便于观察报错)。
  2. 依次将image/png、image/jpeg、image/gif三种格式的图片拖入可编辑区域。
  3. 对行内编辑器(inline editor)重复上述操作。

预期结果:浏览器控制台无任何报错;图片被正确粘贴;生成的<img>标签src属性为 Base64 格式(data:image/png;base64,...等)。

非预期结果:浏览器控制台出现错误;图片不可见。

Scenario 2:拖放不支持的文件类型

操作步骤:

  1. 打开浏览器控制台。
  2. 拖入受支持格式以外的文件,例如.pdf。
  3. 对行内编辑器重复上述操作。

预期结果:浏览器控制台无报错;可编辑区域内容不发生任何变化。

非预期结果:浏览器控制台出现错误;可编辑区域内容被改变。

测试夹具:经典编辑器与行内编辑器并存

配套的 HTML 夹具 draganddropimage.html 展示了测试页的构造方式:同时创建经典编辑器与行内编辑器,并借助bender.tools.env.mobile与CKEDITOR.plugins.clipboard.isFileApiSupported做环境探测,在不支持 File API 的浏览器上直接bender.ignore()跳过测试:

<div id="editor"> <p>Drag and drop image here.</p> </div> <p>Inline editor.</p> <div id="inline" contenteditable="true" style="border:1px solid #000000;"> <p>Drag and drop image here.</p> </div> <script> if ( bender.tools.env.mobile ) { bender.ignore(); } var editor = CKEDITOR.replace( 'editor' ), inline = CKEDITOR.inline( 'inline', { extraPlugins: 'sourcedialog' } ); editor.on( 'loaded', function() { if ( !CKEDITOR.plugins.clipboard.isFileApiSupported ) { bender.ignore(); } } ); </script>

这里透露出一个重要前提:该能力依赖浏览器 File API,因此isFileApiSupported为false的环境(如 IE9 及以下)无法验证本功能。

二、功能背景:4.17.0 的 Base64 拖放图片支持

该功能在 CHANGES.md 中有明确记录,归属于 4.17.0 版本的功能列表:

  • #4612:允许在所有浏览器(除 IE 外)中从剪贴板将图片粘贴为 Base64;
  • #4681:允许将拖放(drag and drop)的图片转为 Base64——这正是本文所讲手动测试的验证对象;
  • #4750:为粘贴/拖放不支持的文件类型增加通知提示。

由此可以看到一条完整的能力演进链:粘贴图片转 Base64 → 拖放图片转 Base64 → 不支持类型给出通知。本手动测试恰好把这三项能力(转换 + 拒绝 + 通知)集成在两个场景中验证。

三、源码级实现原理

3.1 图片转 Base64 的转换监听器

核心逻辑位于 plugins/clipboard/plugin.js。clipboard 插件在init阶段向编辑器的paste事件注册了一个优先级为 1的监听器(数值越小越先执行),用异步的FileReader把图片文件读成 Data URL:

// Convert image file (if present) to base64 string. // Do it as the first step as the conversion is asynchronous and should hold all further paste processing. editor.on( 'paste', function( evt ) { if ( !isFilePasteSupported || !editor.config.clipboard_handleImages ) { return; } var dataObj = evt.data, data = dataObj.dataValue, dataTransfer = dataObj.dataTransfer; // Allow both dragging and dropping and pasting images as base64 (#4681). if ( data || !isFileData( evt, dataTransfer ) ) { return; } var file = dataTransfer.getFile( 0 ); if ( !testImageBase64Support( file ) ) { return; } var fileReader = new FileReader(); // Convert image file to img tag with base64 image. fileReader.addEventListener( 'load', function() { evt.data.dataValue = '<img src="' + fileReader.result + '" />'; editor.fire( 'paste', evt.data ); }, false ); // abort / error 时走正常流程并重新触发 paste(见下方 IE 特判) fileReader.addEventListener( 'abort', function() { setCustomIEEventAttribute( evt ); editor.fire( 'paste', evt.data ); }, false ); fileReader.addEventListener( 'error', function() { setCustomIEEventAttribute( evt ); editor.fire( 'paste', evt.data ); }, false ); fileReader.readAsDataURL( file ); latestId = dataObj.dataTransfer.id; evt.stop(); }, null, null, 1 );

关键设计点:

  • 异步前置:注释明确说明"转换是异步的,因此必须挂起后续所有粘贴处理"。FileReader的load回调中把结果写入evt.data.dataValue并重新fire('paste'),再evt.stop()终止当前这次事件分发,从而保证图片数据就绪后才进入后续的 HTML 过滤与插入流程。
  • 拖放与粘贴共用同一路径:注释Allow both dragging and dropping and pasting images as base64 (#4681)表明,无论图片来自剪贴板粘贴还是拖放,最终都会统一收敛到paste事件上处理——这正是拖放图片能被"粘贴"进编辑器的原因。
  • 失败兜底:FileReader触发abort或error时不会丢弃数据,而是重新触发paste走正常流程。setCustomIEEventAttribute对 IE 设置fileTransferCancel标记,用于防止 IE10+ 在图片加载状态非load时陷入无限循环(见isFileData中对该标记的检查)。

3.2 支持格式白名单与配置开关

testImageBase64Support(plugins/clipboard/plugin.js#L238-L246)定义了可转换的 MIME 类型白名单,并检查配置开关:

function testImageBase64Support( file ) { // Check if turning images into base64 is disabled (#5431). if ( !editor.config.clipboard_handleImages ) { return false; } var supportedImageTypes = [ 'image/png', 'image/jpeg', 'image/gif' ]; return CKEDITOR.tools.indexOf( supportedImageTypes, file.type ) !== -1; }

这与手动测试 Scenario 1 要求验证的三种格式(PNG/JPEG/GIF)完全一一对应。application/pdf不在白名单内,因此 Scenario 2 中拖入 PDF 不会生成<img>,编辑器内容保持不变。

注意:testImageBase64Support在 4.19.0 之后还承担"文件匹配器(file matcher)"的职责——插件通过CKEDITOR.plugins.clipboard.addFileMatcher( editor, matcher )(plugin.js#L1748-L1771)注册校验函数,用于判断某文件是否受支持;对不支持的文件,插件会显示通知,但不会取消 paste 事件,是否真正拒绝/上传由集成方负责。

3.3 "仅文件"判定:避免误伤普通拖放

isFileData(plugins/clipboard/plugin.js#L282-L294)限定只有"仅包含单个文件"的 dataTransfer 才会触发图片转换,防止与编辑器内部的文本/HTML 拖放(内部拖放、跨编辑器拖放)混淆:

function isFileData( evt, dataTransfer ) { // Checking for fileTransferCancel on IE to prevent comparing empty string // from dataTransfer.id and falling into infinite loop (#4681). if ( CKEDITOR.env.ie && evt.data.fileTransferCancel ) { return false; } if ( !CKEDITOR.env.ie && ( !dataTransfer || latestId === dataTransfer.id ) ) { return false; } return dataTransfer.isFileTransfer() && dataTransfer.getFilesCount() === 1; }

同时,插件在paste事件优先级 1 的位置还有一个"不支持文件类型通知"监听器(plugin.js#L158-L184):遍历 dataTransfer 中的文件,凡是isFileTypeSupported判定失败的类型都会被收集进unsupportedFileTypes,最终通过displayUnsupportedFileTypesNotification调用editor.showNotification( ..., 'info', editor.config.clipboard_notificationDuration )弹出提示。消息文案在 plugins/clipboard/lang/en.js:

fileFormatNotSupportedNotification: 'The ${formats} file format(s) are not supported.', fileWithoutFormatNotSupportedNotification: 'The file format is not supported.'

3.4 拖放执行链路:drop → paste

initDragDrop(plugins/clipboard/plugin.js#L1531-L1741)在contentDom阶段为可编辑区域挂接dragstart/dragover/dragend/drop监听。对于来自外部源(如文件系统)的拖放,externalDrop(plugin.js#L1701-L1712)会:

  1. dropRange.select()把光标定位到拖放落点;
  2. firePasteEvents( editor, { dataTransfer: dataTransfer, method: 'drop' }, 1 )触发paste事件——dataTransfer 中的文件随之进入 3.1 的 Base64 转换监听器;
  3. 由于dragend发生在拖放源元素上、外部拖放不会触发它,因此这里显式调用clipboard.resetDragDataTransfer()清理全局拖放状态。

文件头部的执行流程注释(plugin.js#L86-L112)也完整描述了三种拖放分支:内部拖放(带cke-前缀时间戳匹配)、跨编辑器拖放、外部源拖放——外部文件拖放正是走最后一条分支。此外,dragover监听器对 IE 且 dataTransfer 含Files的场景调用preventDefault(),避免浏览器直接用文件路径覆盖文档内容。

四、相关配置项

4.1clipboard_handleImages

定义位于 plugins/clipboard/plugin.js#L3562-L3570:

/** * Whether to use clipboard plugin to handle image pasting and dropping, * turning images into base64 strings on browsers supporting the File API. * * @since 4.17.0 * @cfg {Boolean} [clipboard_handleImages=true] * @member CKEDITOR.config */ CKEDITOR.config.clipboard_handleImages = true;
  • 默认值:true;
  • 引入版本:4.17.0(与本手动测试的@bender-tags标注一致);
  • 作用:决定 clipboard 插件是否接管图片的粘贴与拖放并把图片转为 Base64;
  • 适用前提:浏览器支持 File API(CKEDITOR.plugins.clipboard.isFileApiSupported)。

当该配置为false时,testImageBase64Support直接返回false,图片不会被转换,且由于图片此时落入"不受支持类型"分支,编辑器会弹出"文件格式不受支持"通知。仓库中专门提供了两个手动测试文档佐证这一行为:pasteimagedisable.md 与 dropimagedisabled.md,后者描述"从文件系统拖入图片,预期不插入图片,仅输出自定义图片拖放处理收到的数据"。

关闭该配置的典型场景:集成方希望自己接管图片处理(例如配合上传插件把图片上传到服务器,而不是塞进 Base64)。clipboardimagedisabled.js 即演示了在clipboard_handleImages: false时自定义图片处理器插件可自行消费文件。

4.2clipboard_notificationDuration

定义位于 plugins/clipboard/plugin.js#L3553-L3560:

/** * Duration of the notification displayed after pasting was blocked by the browser. * * @since 4.7.0 * @cfg {Number} [clipboard_notificationDuration=10000] * @member CKEDITOR.config */ CKEDITOR.config.clipboard_notificationDuration = 10000;
  • 默认值:10000(毫秒);
  • 作用:控制不支持文件类型通知的展示时长(单位为毫秒),由editor.showNotification( message, 'info', duration )使用。

五、自动化测试如何验证同一行为

除了手动测试,仓库还提供了与手动测试断言完全对齐的自动化测试,可作为回归验证依据:

5.1 拖放场景:dropimage.js

  • test drop .png/.jpeg/.gif image:模拟拖放事件后,断言最终 HTML 中出现src="data:image/png;base64,fileMockBase64="的<img>(测试用mockFileReader注入伪造的 Base64 结果);
  • test drop unsupported image type:拖入application/pdf,断言编辑器内容保持<p class="p">Paste image here:</p>不变;
  • test dropping unsupported image type shows notification:断言showNotification被调用一次、消息匹配fileFormatNotSupportedNotification、类型为info、时长为clipboard_notificationDuration;
  • (#5431) test dropping image when the clipboard_handleImages configuration option is OFF ...:关闭配置后拖入 PNG,同样只弹通知、不插入图片。

5.2 粘贴场景:pasteimage.js

  • 粘贴 PNG/JPEG/GIF 均断言生成带data-cke-saved-src与src双属性的 Base64<img>;
  • test unsupported file type(application/pdf)、abort、error、clipboard_handleImages: false等分支与拖放测试一一对应;
  • test pasting image alongside other content(对应 #3585/#3625)验证"图片与其他内容同时粘贴时,文本内容优先、图片被忽略"的边界行为。

自动测试与手动测试共同覆盖的场景矩阵完全一致,说明 draganddropimage.md 中"PNG/JPEG/GIF 成功、PDF 拒绝、内容不变、无控制台报错"的预期并非孤例,而是有代码与断言双重保障的稳定契约。

六、验证建议与边界说明

在本地复现手动测试时,可关注以下几点:

  1. 浏览器要求:务必使用支持 File API 的现代浏览器(Chrome、Firefox、Edge);IE10 以下会因isFileApiSupported为false而跳过,且 IE 场景依赖fileTransferCancel标记避免死循环。
  2. 编辑器形态:经典编辑器(CKEDITOR.replace)与行内编辑器(CKEDITOR.inline)都应验证,二者共享同一套paste/drop处理逻辑。
  3. 控制台观察:拖入文件后关注 console 是否有异常;同时可观察编辑器内容中<img>的src是否以data:image/png;base64,等前缀开头。
  4. 格式边界:image/svg+xml、image/webp、application/pdf等均不在白名单内,会被当作不支持类型处理(触发通知、内容不变)。
  5. 内容优先级:若拖放/粘贴的数据中同时包含文本与文件,文本数据(dataValue)优先,图片转换不会覆盖已有内容(见 3.3 的if ( data ) return判断)。
  6. 集成扩展:如需自定义支持格式或接管处理流程,可参考CKEDITOR.plugins.clipboard.addFileMatcher注册自定义匹配器,并配合clipboard_handleImages: false自行实现图片上传逻辑。

综上,tests/plugins/clipboard/manual/draganddropimage.md是验证 CKEditor 4.17.0 "拖放图片转 Base64"(#4681)能力的权威手动验收入口;理解其背后 plugins/clipboard/plugin.js 中"FileReader 异步转换 + paste 事件重放 + MIME 白名单 + 通知兜底"的完整链路,即可在实际集成中准确预判并扩展这一行为。

  • 前端
  • UI组件

【免费下载链接】ckeditor4

The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.

项目地址:https://gitcode.com/gh_mirrors/ck/ckeditor4
点击查看免费下载
上一篇:5分钟搞定B站视频下载:免费解锁大会员4K高清画质
下一篇:Fontsource 字体家族档案:Akatab——Tifinagh 文字排版开源字体实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询