editor.md编辑器,图片跨域上传,前后端分离

解决思路:

不修改原来的editormd文件

通过猴子补丁(monkey patch)的方式,替换editormd内部的上传方法。例如,找到image-dialog.js中处理上传的函数,保存原函数的引用,然后用自定义函数替换

复制代码
    // 初始化编辑器
    function initEditor() {
        // 保存原始图片上传处理函数
        const originalImageUpload = editormd.prototype.executePlugin;

        // 猴子补丁方式覆盖图片上传处理
        editormd.prototype.executePlugin = function(pluginName, options) {
            if (pluginName === "imageDialog") {
                this.imageUploader = function() {
                    const file = this.files[0];
                    const loading = layer.msg('上传中...', {icon: 16, shade: 0.01});

                    // 创建与现有上传组件一致的FormData
                    const formData = new FormData();
                    formData.append('editormd-image-file', file); // 保持参数名称与现有系统一致
                    formData.append('filetype', 0); // 添加系统要求的参数

                    // 使用原始XMLHttpRequest发送保持请求结构
                    const xhr = new XMLHttpRequest();
                    xhr.open('POST', API.getApiUrl('index/upload'));
                    xhr.setRequestHeader('Authorization', 'Bearer ' + API.getToken());
                    
                    xhr.upload.onprogress = function(e) {
                        if (e.lengthComputable) {
                            const percent = (e.loaded / e.total * 100).toFixed(2) + '%';
                            layer.msg('上传进度: ' + percent, {icon: 16, shade: 0.01});
                        }
                    };

                    xhr.onload = function() {
                        layer.close(loading);
                        try {
                            const res = JSON.parse(xhr.responseText);
                            if (res.success === 1) {
                                // 使用编辑器API插入图片
                                const cursor = this.getCursor();
                                this.replaceSelection(`![](${res.url})`, cursor);
                                layer.msg('上传成功', {icon: 1});
                            } else {
                                layer.msg(res.msg || '上传失败', {icon: 2});
                            }
                        } catch(e) {
                            console.error('解析响应失败:', e);
                            layer.msg('上传失败', {icon: 2});
                        }
                    }.bind(taskEditor); // 绑定编辑器实例上下文

                    xhr.onerror = function() {
                        layer.close(loading);
                        console.error('上传失败:', xhr.statusText);
                        layer.msg('网络错误', {icon: 2});
                    };

                    xhr.send(formData);
                };

                // 保持与Editor.md一致的DOM操作
                const fakeInput = document.createElement('input');
                fakeInput.type = 'file';
                fakeInput.name = 'editormd-image-file';
                fakeInput.accept = "image/*";
                fakeInput.onchange = this.imageUploader.bind(fakeInput);
                fakeInput.click();
                
                return false;
            }
            return originalImageUpload.apply(this, arguments);
        };

        // 继续原有编辑器初始化逻辑
        const editorContainer = $('#taskDescription');
        if (editorContainer.is(':visible')) {
            const isMobile = window.innerWidth <= 768;
            console.log('0000',CONFIG.API.getBaseUrl());
            taskEditor = editormd("taskDescription", {
                width: "100%",
                height: isMobile ? 400 : 500,
                path : "../editormd/lib/",
                toolbarIcons : function() {
                    return window.editormdConfig ? 
                        window.editormdConfig.toolbarIcons : 
                        [
                            "undo", "redo", "|",
                            "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|",
                            "h1", "h2", "h3", "h4", "h5", "h6", "|",
                            "list-ul", "list-ol", "hr", "|",
                            "link", "image", "code", "preformatted-text", "code-block", "table", "|",
                            "watch", "preview", "fullscreen", "|",
                            "help"
                        ];
                },
                placeholder: "请详细描述任务需求...",
                saveHTMLToTextarea : true,
                imageUpload : false,
                imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                imageUploadURL : CONFIG.API.getBaseUrl() + "/index/upload?filetype=0",
                crossDomainUpload: true, // 禁用跨域上传
                tex  : true,
                flowChart : true,
                sequenceDiagram : true,
                emoji : true,
                watch: !isMobile, // 移动端关闭实时预览
                onload : function() {
                    console.log('编辑器加载完成');
                }
            });
        } else {
            setTimeout(initEditor, 500); // 延迟检查
        }
    }

解决办法就是:猴子补丁方式覆盖图片上传处理

复制代码
        // 猴子补丁方式覆盖图片上传处理
        editormd.prototype.executePlugin = function(pluginName, options) {
            if (pluginName === "imageDialog") {
                this.imageUploader = function() {
                    const file = this.files[0];
                    const loading = layer.msg('上传中...', {icon: 16, shade: 0.01});

                    // 创建与现有上传组件一致的FormData
                    const formData = new FormData();
                    formData.append('editormd-image-file', file); // 保持参数名称与现有系统一致
                    formData.append('filetype', 0); // 添加系统要求的参数

                    // 使用原始XMLHttpRequest发送保持请求结构
                    const xhr = new XMLHttpRequest();
                    xhr.open('POST', API.getApiUrl('index/upload'));
                    xhr.setRequestHeader('Authorization', 'Bearer ' + API.getToken());
                    
                    xhr.upload.onprogress = function(e) {
                        if (e.lengthComputable) {
                            const percent = (e.loaded / e.total * 100).toFixed(2) + '%';
                            layer.msg('上传进度: ' + percent, {icon: 16, shade: 0.01});
                        }
                    };

                    xhr.onload = function() {
                        layer.close(loading);
                        try {
                            const res = JSON.parse(xhr.responseText);
                            if (res.success === 1) {
                                // 使用编辑器API插入图片
                                const cursor = this.getCursor();
                                this.replaceSelection(`![](${res.url})`, cursor);
                                layer.msg('上传成功', {icon: 1});
                            } else {
                                layer.msg(res.msg || '上传失败', {icon: 2});
                            }
                        } catch(e) {
                            console.error('解析响应失败:', e);
                            layer.msg('上传失败', {icon: 2});
                        }
                    }.bind(taskEditor); // 绑定编辑器实例上下文

                    xhr.onerror = function() {
                        layer.close(loading);
                        console.error('上传失败:', xhr.statusText);
                        layer.msg('网络错误', {icon: 2});
                    };

                    xhr.send(formData);
                };

                // 保持与Editor.md一致的DOM操作
                const fakeInput = document.createElement('input');
                fakeInput.type = 'file';
                fakeInput.name = 'editormd-image-file';
                fakeInput.accept = "image/*";
                fakeInput.onchange = this.imageUploader.bind(fakeInput);
                fakeInput.click();
                
                return false;
            }
            return originalImageUpload.apply(this, arguments);
        };
相关推荐
hi星尘13 分钟前
深度解析:Java内部类与外部类的交互机制
java·开发语言·交互
看到我,请让我去学习14 分钟前
Qt编程-qml操作(js,c++,canvas)
开发语言·qt
橘子编程15 分钟前
Python-Word文档、PPT、PDF以及Pillow处理图像详解
开发语言·python
Ronin3051 小时前
【C++】类型转换
开发语言·c++
mrbone111 小时前
Git-git worktree的使用
开发语言·c++·git·cmake·worktree·gitab
浪裡遊1 小时前
Sass详解:功能特性、常用方法与最佳实践
开发语言·前端·javascript·css·vue.js·rust·sass
真实的菜1 小时前
JVM类加载系统详解:深入理解Java类的生命周期
java·开发语言·jvm
代码讲故事2 小时前
多种方法实现golang中实现对http的响应内容生成图片
开发语言·chrome·http·golang·图片·快照·截图
虾球xz2 小时前
CppCon 2018 学习:EFFECTIVE REPLACEMENT OF DYNAMIC POLYMORPHISM WITH std::variant
开发语言·c++·学习
Allen_LVyingbo2 小时前
Python常用医疗AI库以及案例解析(2025年版、上)
开发语言·人工智能·python·学习·健康医疗