如何解决TinyMCE Blazor自定义图片上传处理器的JSON序列化错误?
解决TinyMCE Blazor自定义图片上传(带JWT认证)的序列化问题
问题核心在于TinyMCE Blazor会将配置字典序列化为JSON传递给JS端,C#的Lambda/委托无法被JSON序列化,所以不能直接把C#逻辑塞到images_upload_handler里。下面是可行的解决方案:
步骤1:调整TinyMCE配置,引用JS全局上传函数
修改Razor页面的配置,将images_upload_handler设为JS全局函数的名称,而非C#代码:
@inject IJSRuntime JS @inject AuthenticationStateProvider AuthState <TinyMCE EditorConf="@editorConf" /> @code { private Dictionary<string, object> editorConf = new Dictionary<string, object> { {"plugins", "autolink media link image emoticons table paste"}, {"toolbar", "undo redo | styles | bold italic underline | table | link image paste "}, {"paste_data_images", "true"}, {"width", "100%"}, {"automatic_uploads", true}, // 指定JS全局函数作为上传处理器 {"images_upload_handler", "tinymceImageUploadHandler"} }; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { // 从认证状态中获取JWT,传递给JS(如果JWT存在localStorage可跳过这步) var authState = await AuthState.GetAuthenticationStateAsync(); var jwtToken = authState.User.FindFirst("access_token")?.Value; if (!string.IsNullOrEmpty(jwtToken)) { await JS.InvokeVoidAsync("setTinyMCEUploadToken", jwtToken); } } } }
步骤2:编写JS上传处理器,添加JWT认证
在wwwroot/scripts/tinymce-upload.js中编写全局上传函数,负责添加JWT并调用后端接口:
// 存储JWT(如果从C#传递) let uploadToken = ''; // 接收C#传递的JWT window.setTinyMCEUploadToken = function(token) { uploadToken = token; }; // TinyMCE上传处理器核心逻辑 window.tinymceImageUploadHandler = function(blobInfo, success, failure, progress) { // 若JWT存在localStorage,可直接读取: // const uploadToken = localStorage.getItem('your_token_key'); const formData = new FormData(); formData.append('file', blobInfo.blob(), blobInfo.filename()); fetch('/UploadImage/', { method: 'POST', headers: { // 添加JWT认证头 'Authorization': `Bearer ${uploadToken}` }, body: formData }) .then(response => { if (!response.ok) throw new Error('图片上传失败'); return response.json(); }) .then(data => { // 将后端返回的图片路径传给TinyMCE success(data.location); }) .catch(error => { failure(error.message); }); };
步骤3:在页面引入JS脚本
在wwwroot/index.html中添加脚本引用:
<script src="scripts/tinymce-upload.js"></script>
步骤4:后端上传接口示例(带JWT认证)
确保后端接口支持JWT认证,并处理文件上传:
[ApiController] [Route("UploadImage")] [Authorize] public class UploadImageController : ControllerBase { private readonly IWebHostEnvironment _webHostEnv; public UploadImageController(IWebHostEnvironment webHostEnv) { _webHostEnv = webHostEnv; } [HttpPost] public async Task<IActionResult> Upload(IFormFile file) { if (file == null || file.Length == 0) return BadRequest("未选择上传文件"); // 创建上传目录 var uploadDir = Path.Combine(_webHostEnv.WebRootPath, "uploads/images"); Directory.CreateDirectory(uploadDir); // 生成唯一文件名 var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; var filePath = Path.Combine(uploadDir, fileName); // 保存文件 using var stream = new FileStream(filePath, FileMode.Create); await file.CopyToAsync(stream); // 返回图片访问路径 return Ok(new { location = $"/uploads/images/{fileName}" }); } }
为什么原来的方案报错?
你之前的代码试图把C# Lambda赋值给images_upload_handler,但TinyMCE Blazor需要将配置序列化为JSON传递给JS,而C#的委托/Lambda类型无法被JSON序列化,因此抛出序列化错误。必须使用JS层面的函数作为上传处理器,再通过JS与C#交互或直接调用后端接口。
内容的提问来源于stack exchange,提问作者FuzzyDunlop
相关产品推荐
相关产品推荐

