You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中为TinyMCE图片上传添加CSRF令牌遇报错

解决Laravel中TinyMCE图片上传的419错误及后续Promise报错

问题分析

  1. 初始的419错误是因为Laravel的CSRF验证机制——上传请求未携带CSRF令牌,被框架拦截。
  2. 自定义images_upload_handler后出现的cannot read properties of undefined (reading 'then')错误,核心原因是TinyMCE 5及以上版本要求images_upload_handler必须返回一个Promise对象,若不返回,编辑器会默认将其视为异步操作并尝试调用then方法,最终触发未定义错误。

修复步骤

1. 确保页面存在CSRF元标签

在Laravel的Blade模板头部添加以下标签(这是独立JS文件获取CSRF令牌的前提):

<meta name="csrf-token" content="{{ csrf_token() }}">

2. 修改images_upload_handler为返回Promise的结构

将原有的XHR逻辑包裹进Promise中,同时完善错误处理逻辑(调用TinyMCE提供的failure回调):

$(document).ready(function() {
    tinymce.init({
        selector: '#body',
        plugins: '...',
        toolbar: '...',
        toolbar_mode: 'floating',
        tinycomments_mode: 'embedded',
        relative_urls: false,
        paste_data_images: true,
        image_title: true,
        automatic_uploads: true,
        file_picker_types: "image",
        // 修复后的上传处理器,返回Promise
        images_upload_handler: function (blobInfo, success, failure) {
            return new Promise(function(resolve, reject) {
                var xhr = new XMLHttpRequest();
                xhr.withCredentials = false;
                xhr.open('POST', '/admin/uploadImg/');

                xhr.onload = function () {
                    if (xhr.status === 200) {
                        try {
                            var json = JSON.parse(xhr.responseText);
                            if (json && typeof json.location === 'string') {
                                success(json.location);
                                resolve(json.location);
                            } else {
                                var errMsg = '返回的JSON格式无效,缺少location字段';
                                console.error(errMsg);
                                failure(errMsg);
                                reject(errMsg);
                            }
                        } catch (e) {
                            var parseErr = '解析响应JSON失败: ' + e.message;
                            console.error(parseErr);
                            failure(parseErr);
                            reject(parseErr);
                        }
                    } else {
                        var httpErr = 'HTTP错误: ' + xhr.status;
                        console.error(httpErr);
                        failure(httpErr);
                        reject(httpErr);
                    }
                };

                // 处理XHR网络错误
                xhr.onerror = function() {
                    var netErr = '网络请求失败,请检查连接';
                    console.error(netErr);
                    failure(netErr);
                    reject(netErr);
                };

                var formData = new FormData();
                formData.append('file', blobInfo.blob(), blobInfo.filename());
                formData.append('_token', $('meta[name="csrf-token"]').attr('content'));

                xhr.send(formData);
            });
        },
        file_picker_callback: function (cb, value, meta) {
            var input = document.createElement("input");
            input.setAttribute("type", "file");
            input.setAttribute("accept", "image/*");
            input.onchange = function () {
                var file = this.files[0];

                var reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = function () {
                    var id = "blobid" + new Date().getTime();
                    var blobCache = tinymce.activeEditor.editorUpload.blobCache;
                    var base64 = reader.result.split(",")[1];
                    var blobInfo = blobCache.create(id, file, base64);
                    blobCache.add(blobInfo);
                    cb(blobInfo.blobUri(), { title: file.name });
                };
            };
            input.click();
        }
    });
});

3. 后端接口配合

确保/admin/uploadImg/接口正确处理上传,并返回包含location字段的JSON响应,示例:

return response()->json([
    'location' => Storage::url($uploadedFile->path())
]);

内容的提问来源于stack exchange,提问作者yasir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:03:31