MediaWiki 默认不支持从剪贴板直接粘贴图片到编辑框。支持粘贴你按下 Ctrl+V,图片浏览器只会把图片当成文件路径或者二进制数据,支持粘贴编辑器根本不认。图片这个限制让很多从 Word 或网页复制内容的支持粘贴用户感到别扭——文字能粘,图片却要手动上传,图片再插入链接,支持粘贴流程断成两截。图片
但这事有解。支持粘贴核心思路是图片:在编辑器加载时挂一个 paste 事件监听器,拦截剪贴板里的支持粘贴图片数据,走 MediaWiki 的图片上传 API 把图片存到服务器,拿到文件名后再把 Wiki 图片语法插到光标位置。支持粘贴整个过程对用户来说就是图片一次粘贴,和用桌面编辑器没区别。支持粘贴
实现路径拆开看
浏览器端的 ClipboardEvent 里有个 clipboardData.items,遍历它就能找到类型为 image/* 的条目。用 getAsFile() 取出 Blob,再包一个 FormData,字段名通常用 file。请求发到 api.php?action=upload,带上 CSRF token——这个 token 可以通过 action=query&meta=tokens&type=csrf 提前拿到。
上传成功后,API 返回的 JSON 里有 upload.result.filename。把它拼成 [[File:xxx.png]] 或 [[File:xxx.png|thumb]],通过编辑器的 insertContent 方法塞进去。如果用的是 WikiEditor 或 VisualEditor,插入方式略有差别,但原理一样。
我见过一个实际部署案例:某内部知识库在 Common.js 里加了不到 80 行代码,就实现了粘贴截图自动上传。他们额外做了一件事——限制图片大小不超过 2MB,超过就在页面顶部弹个提示条,避免有人把整页设计稿粘进来撑爆存储。
几个容易踩的坑
权限。匿名用户通常没有 upload 权限,粘贴会静默失败。最好在监听器里先判断 wgUserName 是否存在,或者直接检查 wgUserGroups 里有没有 upload 权限。没权限就提示“请先登录再粘贴图片”。
文件名冲突。如果每次都叫 paste.png,第二次上传就会报错。常见做法是用时间戳加随机数:paste-20250115-143022-a3f9.png。也可以让用户在弹出的对话框里改名字,但那样就失去了“无感粘贴”的流畅感。我倾向于自动命名,后期需要整理再批量重命名。
跨域和 token 过期。如果 Wiki 部署在子路径下,api.php 的 URL 别写死,用 mw.config.get('wgScriptPath') 拼。CSRF token 有有效期,长时间不操作后第一次粘贴可能失败,可以捕获 badtoken 错误码,重新取一次 token 再重试上传。
有没有现成扩展
有。Extension:ClipboardImage 就是干这个的,但维护状态一般,只兼容部分皮肤。另一个思路是用 VisualEditor,它原生支持拖拽和粘贴图片——前提是你已经启用了 VisualEditor 并且配置好了上传后端。如果你不想写代码,直接上 VisualEditor 是最省事的方案。
自己写监听器的好处是可控。比如你可以决定图片是直接上传到主命名空间,还是先扔进一个待审核分类;也可以压缩图片再上传,减少带宽。我见过有人用 canvas.toBlob() 把截图转成 WebP 再传,体积直接砍半。
说到底,MediaWiki 的图片粘贴不是“能不能”的问题,而是“愿不愿意花半小时配一下”的问题。配好之后,编辑体验会顺滑很多,尤其是写教程、记笔记这类需要频繁截图的场景。