必须集成unisharp/laravel-filemanager(lfm)打通前后端文件管理链路,安装后发布配置与静态资源,确保public/vendor/laravel-filemanager/js/lfm.js存在;再分别为ckeditor5、tinymce、summernote配置lfm弹窗回调以支持图片插入与上传。

要在Laravel项目中让富文本编辑器支持点击插入图片、拖拽上传文件、浏览服务器已有资源,必须打通前端编辑器与后端文件管理系统的通信链路,不能只靠前端JS硬编码路径或本地模拟。
选择兼容的文件管理器并引入前端资源
UniSharp/laravel-filemanager(LFM)是当前 Laravel 生态中最成熟、文档最全、与主流编辑器深度适配的文件管理方案。它提供统一的 /laravel-filemanager 端点,所有前端调用都走这个接口,无需为每个编辑器重复开发上传逻辑。
执行 composer require unisharp/laravel-filemanager 安装后,运行 php artisan vendor:publish --tag=lfm_config 生成配置文件,再执行 php artisan vendor:publish --tag=lfm_public 发布前端静态资源到 public/vendor/laravel-filemanager 目录。
确保 public/vendor/laravel-filemanager/js/lfm.js 已成功生成——【缺少这个文件会导致所有前端调用直接 404】。
为 CKEditor5 配置文件浏览按钮
CKEditor5 默认不带文件浏览功能,需手动注入 LFM 的弹窗桥接逻辑。
在初始化编辑器的 JS 中,添加 customUploadAdapter 和 toolbar 配置:
第一步:定义 LFM 弹窗打开函数
function openKCFinder() { window.kcf = window.open('/laravel-filemanager?callback=selectFile', 'kcfinder_textbox', 'status=0, toolbar=0, width=800, height=500, resizable=1, menubar=0, location=0'); }
第二步:在 CKEditor5 配置中启用 imageUpload 插件,并绑定回调
ClassicEditor.create(document.querySelector('#editor'), { toolbar: ['heading', '|', 'bold', 'italic', 'link', 'imageUpload', 'blockQuote', 'undo', 'redo'], image: { upload: { types: ['jpeg', 'png', 'gif', 'webp'] }, } }).then(editor => { const imgButton = editor.ui.componentFactory.create('imageUpload'); editor.ui.view.toolbar.items.add(imgButton); editor.plugins.get('ImageUploadEditing').on('fileUploadRequest', (evt, data) => { const xhr = data.xhr; xhr.upload.addEventListener('progress', evt => { editor.editing.view.notifyDirty(); }); }); }).catch(error => console.error(error));
第三步:在页面底部添加回调函数,接收 LFM 返回的文件路径
window.selectFile = function(url, file) { const editor = ClassicEditor.instances[0]; editor.model.change(writer => { const imageElement = editor.model.schema.createElement('imageBlock'); imageElement.setAttribute('src', url); editor.model.insertContent(imageElement); }); };
TinyMCE 集成 LFM 的两种方式
方法一:使用官方推荐的 file_picker_callback(推荐用于新版 TinyMCE 6+)
在 TinyMCE 初始化配置中加入:
tinymce.init({ selector: '#mytextarea', plugins: 'image link', toolbar: 'image', file_picker_callback: function(callback, value, meta) { let x = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth; let y = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight; let cmsURL = '/laravel-filemanager?lang=' + tinymce.settings.language + '&callback=customSelectFile'; tinyMCE.activeEditor.windowManager.openUrl({ url: cmsURL, title: 'File Manager', width: x * 0.8, height: y * 0.8, resizable: 'yes' }); }, });
方法二:手动绑定按钮触发(兼容老版本或需要自定义 UI 时)
在页面中添加一个隐藏的 input[type="file"] 和一个 visible button,点击 button 后执行 document.getElementById('lfm').click(),再监听 change 事件读取选中文件并插入编辑器。这种方式需自行处理跨域、CSRF token、图片预览等细节,【不推荐新手采用】。
Summernote 嵌入式弹窗集成
Summernote 本身不支持外部文件管理器,但可通过自定义按钮扩展实现。
先注册插件:
$.summernote.plugins['lfm'] = function(context) { const self = this; const ui = $.summernote.ui; const button = ui.button({ contents: '<i class="fa fa-picture-o"></i> 图片库', tooltip: '从服务器选择图片', click: function() { const lfm = window.open('/laravel-filemanager?&callback=lfmCallback', 'lfm', 'width=800,height=500'); window.lfmCallback = function(url, path) { context.invoke('editor.insertImage', url); }; } }); context.memo('button.lfm', function() { return button.render(); }); };
再在 Summernote 初始化时启用:
$('#summernote').summernote({ height: 300, toolbar: [ ['insert', ['lfm', 'picture', 'link']] ], });
这一步必须保证 window.lfmCallback 是全局可写函数,否则回调无法触发插入动作。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











