news 2026/7/3 9:49:24

为UEditor增加图片删除功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为UEditor增加图片删除功能

为UEditor增加图片删除功能

在开发一个内容管理系统时,最怕遇到“功能越更新越少”的情况。最近项目里用的 UEditor 升级到 1.2.5 版本后,团队同事集体炸锅:图片管理页面里的删除按钮不见了!

翻遍官方文档和更新日志,没找到任何解释。原来是为了“简化逻辑”,直接把删除功能砍了。可问题是,服务器上的上传图片越积越多,总不能每次都让我们登录服务器手动删文件吧?这不仅效率低,还容易误删、漏删。

没办法,只能自己动手补回来。今天就来完整还原这个被“优化掉”的功能——给 UEditor 加上图片双击删除能力,并确保前后端协同工作、安全可控。


核心思路:缺什么补什么,通信链路自己搭

UEditor 的图片管理本质上是一个简单的“浏览 + 加载”流程:前端请求某个接口获取图片列表,然后渲染成缩略图展示。原本应该有的“删除”操作,在新版中只是少了前后端的对接逻辑,并非底层不支持。

所以我们的目标很明确:

  1. 服务端:让imageManager.ashx支持接收删除请求;
  2. 客户端:在图片上绑定双击事件,发送删除指令并刷新视图。

整个过程不需要动编辑器核心代码,只需扩展现有逻辑即可。


后端改造:为 imageManager.ashx 添加 del 操作

打开.NET项目的ueditor/net/imageManager.ashx文件,这是处理图片列表的核心处理器。

当前它只响应action=get来拉取图片路径,我们要新增一种行为:action=del,用于删除指定文件。

✅ 修改后的完整逻辑如下(关键部分已标注):

<%@ WebHandler Language="C#" Class="imageManager" %> using System; using System.Web; using System.IO; public class imageManager : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; // 可配置的存储目录(可根据实际路径调整) string[] paths = { "upload", "upload1" }; string[] filetype = { ".gif", ".png", ".jpg", ".jpeg", ".bmp" }; string action = context.Server.HtmlEncode(context.Request["action"]); // 获取图片列表 if (action == "get") { string str = string.Empty; foreach (string path in paths) { DirectoryInfo info = new DirectoryInfo(context.Server.MapPath(path)); if (info.Exists) { foreach (DirectoryInfo dir in info.GetDirectories()) { foreach (FileInfo file in dir.GetFiles()) { if (Array.IndexOf(filetype, file.Extension.ToLower()) != -1) { str += path + "/" + dir.Name + "/" + file.Name + "ue_separate_ue"; } } } } } context.Response.Write(str); } // ===================== 新增:删除功能 ===================== else if (action == "del") { string fileName = context.Server.HtmlEncode(context.Request["fileName"]); if (string.IsNullOrEmpty(fileName)) { context.Response.Write("error"); return; } bool deleted = false; try { foreach (string basePath in paths) { string fullPath = context.Server.MapPath(basePath); DirectoryInfo rootDir = new DirectoryInfo(fullPath); if (!rootDir.Exists) continue; foreach (DirectoryInfo subDir in rootDir.GetDirectories()) { foreach (FileInfo file in subDir.GetFiles(fileName)) { if (Array.IndexOf(filetype, file.Extension.ToLower()) == -1) continue; File.Delete(file.FullName); deleted = true; break; } if (deleted) break; } if (deleted) break; } context.Response.Write(deleted ? "success" : "notfound"); } catch { context.Response.Write("error"); } } // ======================================================== } public bool IsReusable => false; }

📌 关键设计说明:

  • 使用action=del区分操作类型,避免与原有逻辑冲突;
  • 遍历所有允许的上传目录,防止因路径嵌套导致找不到文件;
  • 删除成功返回"success",失败统一回"error",前端据此判断结果;
  • 增加对空参数校验,提升健壮性;
  • 不使用硬编码路径,便于后期迁移或扩展多目录管理。

⚠️ 注意:这里没有立即加入权限验证,生产环境务必补充身份检查(见后文建议)。


前端增强:双击图片触发删除确认

接下来进入ueditor/dialogs/image/image.js,这是图片对话框的控制脚本。

我们需要在每张加载出来的图片上绑定一个双击事件,弹出确认框,调用同一个imageManager.ashx接口执行删除。

✅ 在图片加载回调中添加以下代码:

找到onsuccess回调函数内创建<img>元素的位置,在设置完srcdata_ue_src后插入如下逻辑:

// 绑定双击删除事件 img.ondblclick = function () { var me = this; var src = me.getAttribute('src', 2); // 获取真实地址 var filename = src.substring(src.lastIndexOf('/') + 1); // 提取文件名 if (!confirm('确定要删除这张图片吗?此操作不可恢复!')) return; ajax.request(editor.options.imageManagerUrl, { method: 'POST', timeout: 5000, content: { action: 'del', fileName: filename }, onsuccess: function (xhr) { var res = xhr.responseText; if (res === 'success') { // 从界面移除该元素 var container = me.parentNode; container.parentNode.removeChild(container); alert('✅ 删除成功!'); } else if (res === 'notfound') { alert('⚠️ 文件未找到,请刷新重试'); } else { alert('❌ 服务器删除失败,请检查路径或权限'); } }, onerror: function () { alert('⛔ 网络异常,删除请求发送失败'); } }); };

💡 设计细节解析:

  • 利用getAttribute('src', 2)获取原始 URL(兼容 UEditor 的懒加载机制);
  • 通过lastIndexOf('/')提取文件名,确保传参准确;
  • 使用ajax.request发起 POST 请求,保持与原生风格一致;
  • 成功后同步移除 DOM 节点,实现“即时反馈”;
  • 对不同错误类型做了简单区分提示,用户体验更友好。

小技巧:你可以将提示语改为中文更口语化的表达,比如“真要删?”、“手滑了吗?”等,增加交互趣味性。


功能测试:四步验证是否生效

修改完成后,按以下步骤进行验证:

  1. 清理浏览器缓存,重启 IIS 或开发服务器;
  2. 打开 UEditor 编辑器,点击【图片】按钮进入“网络图片”或“本地图片”选项卡;
  3. 查看已上传的图片列表是否正常显示;
  4. 双击任意一张图片 → 弹出确认框 → 点击确定 → 图片消失 + 服务器对应文件被删除

如果一切顺利,恭喜你,已经成功复活了一个“被阉割”的实用功能!


安全加固:别让便利变成漏洞

虽然功能实现了,但直接开放文件删除接口是非常危险的操作。以下是几个必须考虑的进阶优化点:

🔐 1. 添加用户身份验证

ProcessRequest开头加入登录判断:

if (!context.User.Identity.IsAuthenticated) { context.Response.Write("unauthorized"); context.Response.StatusCode = 401; return; }

配合 Web.config 设置仅授权用户可访问:

<location path="ueditor/net/imageManager.ashx"> <system.web> <authorization> <allow roles="admin,editor" /> <deny users="*" /> </authorization> </system.web> </location>

🛡️ 2. 限制可删除路径范围

不要允许删除任意路径下的文件。可以通过正则过滤传入的fileName,只接受纯文件名(不含路径符):

if (fileName.Contains("/") || fileName.Contains("\\") || fileName.Contains("..")) { context.Response.Write("invalid"); return; }

同时确保File.Delete的路径拼接始终基于预设根目录。

📜 3. 增加操作日志记录

建议记录每一次删除行为,方便后续审计:

System.Diagnostics.EventLog.WriteEntry( "UEditorImageDelete", $"用户 {context.User.Identity.Name} 于 {DateTime.Now} 删除了文件 {filename}" );

或者写入自定义日志文件。

♻️ 4. 实现软删除 / 回收站机制(推荐)

与其直接物理删除,不如先移动到recycle/目录下保留 7 天:

string recyclePath = context.Server.MapPath("upload/recycle"); if (!Directory.Exists(recyclePath)) Directory.CreateDirectory(recyclePath); string targetFile = Path.Combine(recyclePath, fileName); File.Move(file.FullName, targetFile); // 移动而非删除

再配合定时任务定期清理回收站,既能防误删,又不失灵活性。


总结:工具服务于人,而不是反过来

UEditor 这类开源组件的优势在于高度可定制。即使官方出于某种考量移除了某些功能,只要我们理解其通信模型和结构设计,就能快速补全甚至超越原生体验。

这次我们完成的功能虽小,却体现了开发者应有的态度:不盲从更新,也不被动忍受缺陷。当你发现某个“不合理”的改变影响了工作效率,最好的回应方式不是抱怨,而是动手解决。

工具是死的,人才是活的。真正的生产力,来自于你能让它为你所用,而不是反过来。


如果你也在用 UEditor 的 .NET 版本,可以直接套用本文方案。PHP 或 Java 版原理完全相同,只需将后端删除逻辑移植过去即可。如果有需要,我也可以提供其他语言版本的实现参考。

希望这篇实战记录能帮你省下几小时折腾时间。如遇问题欢迎留言交流,一起完善这套“轻量级图片治理”方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 22:00:15

Linux C多线程编程入门与主线程等待技巧

Linux C多线程编程入门与主线程等待技巧 在现代系统编程中&#xff0c;单线程已经难以满足对性能和响应能力的要求。尤其是在服务器、嵌入式设备或后台服务开发中&#xff0c;并发处理几乎成了标配。而Linux环境下最基础、最直接的并发手段之一&#xff0c;就是使用POSIX线程&a…

作者头像 李华
网站建设 2026/7/1 22:00:14

手把手教你部署Open-AutoGLM沉思网站:5步实现AI自主运营

第一章&#xff1a;Open-AutoGLM沉思网站项目概述Open-AutoGLM 是一个基于开源理念构建的智能对话与内容生成平台&#xff0c;旨在融合大语言模型能力与前端交互设计&#xff0c;打造可自迭代、可扩展的“沉思式”人机对话系统。该项目不仅支持自然语言理解与生成&#xff0c;还…

作者头像 李华
网站建设 2026/7/1 21:58:43

AI编译器实战:从零手写算子融合与自动调度系统

摘要&#xff1a;本文将撕开AI编译器的神秘面纱&#xff0c;从零手写一个支持算子融合、自动调度、循环优化的深度学习编译引擎。不同于调用TVM/MLIR的API&#xff0c;我们将完整实现Halide风格的调度原语、polyhedral模型、自动 tiling&vectorization 等核心机制。完整代码…

作者头像 李华
网站建设 2026/7/1 21:56:27

Open-AutoGLM沉思引擎三大核心算法曝光(仅限内部资料流出)

第一章&#xff1a;Open-AutoGLM沉思引擎的诞生背景与演进路径在人工智能技术迅猛发展的背景下&#xff0c;大语言模型&#xff08;LLM&#xff09;逐渐从通用化推理向专业化、自动化决策演进。Open-AutoGLM沉思引擎正是在此趋势下应运而生&#xff0c;旨在构建一个具备自主推理…

作者头像 李华
网站建设 2026/7/1 23:15:57

梯度下降法原理与线性回归应用

梯度下降法原理与线性回归应用 在机器学习的世界里&#xff0c;我们常常面对这样一个核心问题&#xff1a;如何让模型“学会”从数据中提取规律&#xff1f;答案往往归结为一个数学过程——优化。而在这其中&#xff0c;梯度下降法就像一位不知疲倦的探路者&#xff0c;在复杂的…

作者头像 李华
网站建设 2026/7/1 18:49:10

为什么顶尖团队都在悄悄测试Open-AutoGLM?6个你不知道的生产力跃升技巧

第一章&#xff1a;Open-AutoGLM的技术演进与行业影响Open-AutoGLM作为新一代开源自动语言生成模型&#xff0c;代表了自然语言处理领域从封闭生态向开放协作的重要转变。其技术架构融合了大规模预训练、动态推理优化与模块化任务适配机制&#xff0c;在保持高性能的同时显著降…

作者头像 李华