UEditor 1.3.x 上传去 Flash 化套装
UEditor 1.3.x 的图片上传依赖 Flash,现代浏览器已经彻底移除 Flash,表现为弹窗里本地上传那一栏是空白或点了没反应。
这份套装用一个独立插件把它换成 HTML5 直传(
<input type="file"> + FormData + XMLHttpRequest),
并顺手修掉内置 autoupload(粘贴/拖拽)传参不一致导致后端报错的问题。适用范围
ㅤ | ㅤ |
适用版本 | UEditor 1.3.x( UE.version 可确认)。1.4.x 起官方自带 HTML5 上传,不需要这套 |
后端 | 不用改。沿用 1.3.x 原有接口约定 |
UEditor 本体 | 不用改。 ueditor.all.min.js / ueditor.all.js 一个字节都不动 |
改动量 | 新增 1 个 js 文件 + 每个用到编辑器的页面加 1 行 <script> |
浏览器 | 需要 FormData(IE10+)。IE9 及以下自动跳过、退回原弹窗 |
覆盖范围 | 图片的「点按钮上传」「粘贴」「拖拽」三条链路。附件/视频见第 7 节 |
1. 要解决的三个问题
问题 1:点工具栏「插入图片」,本地上传不能用
1.3.x 的
dialogs/image/image.html 本地上传走 imageUploader.swf。Flash 没了,这一栏就废了。问题 2:粘贴 / 拖拽图片,后端报错
内置
autoupload 插件发的请求和点按钮那条不一致。在 bundle 里搜 "autoupload" 能看到:于是
type 出现两次:query string 里是 IMAGE,multipart 表单域里是 ajax。
Java 侧 request.getParameter("type") 在 multipart 请求下优先取表单域,后端拿到 ajax,
进不了图片分支就报错。点按钮那条只发一个 type,所以是好的 —— 这就是"两条链路传参不一样"的来源。问题 3:粘贴失败没有任何提示
内置
autoupload 的响应处理整个包在 try { ... } catch (d) { } 里,
解析失败、后端返错,页面上一点提示都没有,只能在 Network 面板里看出来。2. 插件代码
存成
ueditor.h5upload.js,放在 ueditor.all.min.js 同目录。不含任何项目特定内容,可直接拿走用。3. 接入
每个用到编辑器的页面,在
ueditor.all.min.js 之后加一行:顺序不能反。
ueditor.all.min.js 开头有 UE.plugins = {},插件放前面会被清空,静默失效、不报错。实例化代码一个字不用改:
插件挂在
UE.plugins 上,每个实例初始化时各跑一次,一个页面多个编辑器也没问题。批量找需要加这行的页面:
4. 配置项
都在
ueditor.config.js,插件全部有默认值,一个都不配也能跑。配置项 | 默认值 | 说明 |
imageUrl | UEditor 自带 | 上传地址。原样使用,不会额外拼参数 |
imageFieldName | upfile | 文件字段名。改了后端要跟着改 |
imagePath | "" | 返回地址的前缀。拼在后端返回的 url 前面 |
imageMaxSize | 10M | 单张大小上限(字节) |
imageAllowFiles | .png .jpg .jpeg .gif .bmp | 允许的后缀,同时用于 <input accept> |
h5upload | 不配即启用 | 设 false 关掉插件,恢复原来的 Flash 弹窗 |
前三个是 UEditor 原有配置,后三个是这个插件加的。
imageMaxSize/imageAllowFiles是前端校验,只为了少发一次没用的请求。 后端必须自己再校验一遍 —— 前端这层随便绕。
5. 后端接口约定
沿用 1.3.x 原有约定,所以后端不用改。
请求
注意插件只发文件字段,不会额外加
type 之类的参数 —— 该带的参数请写在 imageUrl 的 query string 里。
这正是内置 autoupload 出问题的地方(见第 1 节问题 2)。响应
判定规则:
情况 | 结果 |
有 url,且 state 缺失或为 SUCCESS | 成功,插入 imagePath + url |
state 是别的值 | 失败,把 state 的值当错误信息弹出来 |
没有 url | 失败,提示"服务器没有返回地址" |
HTTP 非 200 / 响应不是合法 JSON | 失败,提示 HTTP 状态码 |
两点提醒:
- 响应必须是严格 JSON(
JSON.parse能解析)。内置插件用new Function("return " + res)能吃单引号、能吃不带引号的 key,这个插件不行。
state会原样显示给用户。别往里塞异常堆栈或服务器内部路径。
6. UEditor 内部的三个接线点
想改这个插件、或排查它为什么没生效,这三处是关键。都在 bundle 里搜关键字就能定位,不用记行号。
接线点 1:dialog 实例存在哪
搜
_dialogs[ —— 工具栏构建时把每个弹窗实例挂到 editor.ui._dialogs,key 是 命令名 + "Dialog",
图片就是 insertimageDialog。构建发生在 initEditorUI 里、ready 事件之前,所以在 ready 里改一定能拿到。接线点 2:谁会打开这个 dialog(两条路径)
路径 B 不走
render。 所以 render 和 open 必须都截 —— 只截 open 的话,
路径 A 已经被 render 把 iframe 建出来了,Flash 的 image.html 照样加载。接线点 3:插入图片的命令
搜
UE.commands.insertimage。收单个对象或数组:行为:光标停在图片上时替换那张图,否则在光标处插入;多个时每张各占一段。
_src 是 UEditor 自己的原图地址标记,跟着 src 写就行。插件加载顺序(搜
UE.plugin.load)这个顺序决定了关掉 autoupload 只能在实例化前用同名
register 覆盖,见下面坑 2。7. 八个坑
type参数撞车(粘贴报错的根因)imageUrl上已有?type=IMAGE,内置autoupload又append("type", "ajax")。 Java 侧request.getParameter("type")在 multipart 请求下优先取表单域,后端拿到ajax就报错。 排查方法:Network 面板对比点按钮和粘贴两次请求的 Payload,多出来的参数一眼可见。
- 关掉内置插件必须在实例化之前,
setOpt来不及 在插件里写me.setOpt({autoupload: false})无效 —— 注册式插件先跑, 等UE.plugins.h5upload执行时 autoupload 的ready监听已经绑上去了。 正确做法是文件加载时用同名UE.plugin.register('autoupload', ...)覆盖(register按 name 存 map,同名直接覆盖)。
render和open都要截 见上面接线点 2。只截一个的话 Flash 弹窗还是会被加载。
- 剪贴板图片没有文件名
file.name是空的,直传后端取不到后缀。按 MIME 拼成blob.png这种。 也因为没有文件名,粘贴/拖拽那条只能校验大小、没法校验后缀,后端务必自己查。
input.value要先清空 不清的话连续选同一张图不触发change,表现为"第二次点没反应"。
- 多张图等全部传完再一次性插入
逐张插入时网络快慢不同会导致插入顺序和选择顺序不一致。
实现上用
results[index]按下标回填、pending计数归零才插入。
- 混合粘贴不能拦 剪贴板里同时有图和文字(从 Word 复制那种)时直接 return,交给 UEditor 原来的粘贴逻辑。 全拦下来会把带格式的正文粘贴弄坏。这个判断照抄内置插件。
window.top.layer要包 try/catch 页面被跨域 iframe 嵌套时访问window.top会抛安全异常,把上传成功的流程一起带崩。
8. 扩展到附件 / 视频
附件、视频弹窗是同样的 Flash 问题,思路完全一致:截掉对应 dialog 的
render/open,
弹文件框,传完调对应命令插入。差异在这张表:ㅤ | 图片 | 附件 | 视频 |
dialog key | insertimageDialog | attachmentDialog | insertvideoDialog |
上传地址配置 | imageUrl | fileUrl | videoUrl |
路径前缀配置 | imagePath | filePath | videoPath |
字段名配置 | imageFieldName | fileFieldName | videoFieldName |
插入方式 | execCommand('insertimage', [{src, _src}]) | 无现成命令,见下 | execCommand('insertvideo', [{url, width, height, align}], 'upload') |
成熟度不一样,照抄前先看清:
- 图片 —— 本套装已实现并测过。
- 视频 ——
insertvideo命令签名已在 bundle 里核对(搜commands.insertvideo, 第三个参数传'upload'时用edui-upload-video类名走 video 标签,否则走 embed)。但没有实测。
- 附件 —— 核心 bundle 里没有
insertfile命令,附件是dialogs/attachment/attachment.html自己拼<a>标签再insertHtml的。要复刻得先读那个 dialog 文件,抄它的 HTML 结构和 class (关系到列表样式和图标)。这套装没做也没验证。
建议一次只扩一种,各自实测。
9. 已知限制
- 图片属性编辑没了。原弹窗能改 URL、宽高、对齐、边距,现在点「编辑」直接变成"换一张图"。
对齐用工具栏按钮,缩放靠拖拽把手(需
scaleEnabled: true)。
- 没有上传进度。大文件上传时没有任何反馈。要做的话监听
xhr.upload.onprogress。
- IE9 及以下不支持。没有
FormData,插件自动跳过、退回原 Flash 弹窗(等于还是不能上传,但不报错)。
- 截图、涂鸦仍依赖 Flash(
snapscreen/scrawl),本套装没动。
- 同名 register 覆盖是"不受支持"的用法。UEditor 官方没承诺
register可覆盖, 升级小版本时值得回归一下(1.3.x 内部就是按 name 存 map,同名覆盖是必然行为,但仅限 1.3.x)。
10. 上线前必须确认
ueditor.h5upload.js 已部署,且 <script> 在 ueditor.all.min.js 之后每个用到编辑器的页面都加了(
grep -rl "ueditor.all" 挨个核)三条链路各试一次:点按钮选图、粘贴截图(Win+Shift+S 截完直接粘)、拖文件进编辑区
一次多选几张图,确认插入顺序和选择顺序一致
故意传一个超限的大文件、一个
.txt,确认有提示而不是静默失败后端故意返个错,确认错误信息弹出来了(内置插件这里是完全静默的)
点已插入的图片 →「编辑」,确认是换图而不是弹出空白框
从 Word 复制一段带格式的图文混排内容粘贴,确认排版没坏
保存后重新打开,确认图片地址没丢(
imagePath 前缀拼接是否正确)前台展示页确认图片能正常显示(有的项目有 HTML 过滤器会改写
src)后端已独立校验类型和大小(前端那层随便绕)
- 作者:IMyself
- 链接:https://blog.lmyself.top/article/3d8ee568-45a2-80fd-a003-d0ce3c5a8d8d
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章










