当前位置: 首页 > news >正文

为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 版原理完全相同,只需将后端删除逻辑移植过去即可。如果有需要,我也可以提供其他语言版本的实现参考。

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

http://www.zskr.cn/news/158262.html

相关文章:

  • 如何查询自己是否拥有软件著作权证书呢? - 还在做实验的师兄
  • python笔记-文件
  • 从零开始学LlamaIndex Agent:收藏这份指南,轻松掌握大模型智能体开发
  • 矩阵论的奠基与现代科技应用
  • YOLO-NAS训练自定义数据集全指南
  • Excel实用操作技巧大全
  • 用Excel实现层次聚类法进行聚类分析
  • 2025年甲醛检测公司推荐:靠谱的甲醛检测服务公司有哪些? - mypinpai
  • 大疆机甲大师S1深度测评:硬核组装与编程乐趣
  • 2025年国内回购率高榜:无接头钢丝绳厂商大揭秘,合成纤维吊装带/链条吊具/钢坯专用索具/抛缆绳,钢丝绳厂家电话 - 品牌推荐师
  • Open-AutoGLM部署核心技术揭秘,掌握它你也能成为AI工程高手
  • 电商客服大模型微调全攻略:从数据构建到实战应用
  • 登录验证码的原理与实现
  • 为什么顶尖团队都在用AutoGLM?:对比5大主流AutoML框架后的结论
  • 软著查询在哪里查才最权威?第三方平台会不会泄露数据? - 还在做实验的师兄
  • 查询软著登记证书的注意事项?查询软著证书的真假去哪里查询 - 还在做实验的师兄
  • 揭秘大模型背后的“特级教师“:数据标注员的前世今生与未来
  • dropClust:高效处理大规模单细胞RNA聚类
  • 路由器配置的综合实验
  • 2025年儿童手机管控机构服务推荐,儿童手机管控机构哪家权威、联系方式全解析 - 工业品牌热点
  • APP软著如何查询?查不到软著证书是怎么回事? - 还在做实验的师兄
  • win10找回自带的windows照片查看器——打开jpg、png、gif、psd其他格式的图片
  • HCJ-9201全自动绝缘油耐压试验机,上海徐吉电气出品 - 品牌推荐大师1
  • 【资深架构师亲授】Open-AutoGLM生产级部署方案:高并发下的稳定性优化秘诀
  • 解决双击AnacondaNavigator没有反应
  • 2025年有实力的海关数据品牌企业推荐:比较不错的海关数据品牌企业有哪些? - 工业品网
  • 2025年12月读写器厂家推荐,rfid读写器、超高频读写器、超高频rfid读写器厂家选择指南 - 品致汇
  • 手写汉字对比
  • LabelImg与LabelMe安装及JSON标注解析
  • Ubuntu 18.04下搭建GPU加速的YOLOv5环境