CKEditor文件上传接口断点响应正常但浏览器返回空列表问题
CKEditor文件上传接口返回空列表问题
我基于Stack Overflow代码实现了适配CKEditor的文件上传Controller Action,接口上传完成后应返回包含文件URL的JSON响应。调试时断点查看success对象结构符合预期,但浏览器端接收到的却是空列表。
Controller Action代码
[HttpPost] public async Task<ActionResult> Upload(IFormFile upload, string CKEditorFuncNum, string CKEditor, string langCode) { var user = await _userManager.GetUserAsync(User); var admin = _context.LeagueAdmins.Include(i => i.League).FirstOrDefault(i => i.User.Id == user.Id); if (user == null) { throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } if (upload.Length <= 0) return null; if (!upload.IsImage()) { var NotImageMessage = "You must upload a picture"; dynamic NotImage = JsonConvert.DeserializeObject("{ 'uploaded': 0, 'error': { 'message': \"" + NotImageMessage + "\"}}"); return Json(NotImage); } var fileName = Guid.NewGuid() + Path.GetExtension(upload.FileName).ToLower(); Image image = Image.FromStream(upload.OpenReadStream()); int width = image.Width; int height = image.Height; if ((width > 2000) || (height > 2000)) { var DimensionErrorMessage = "Your image is too big. It must be a maximum of 2000px height and width"; dynamic stuff = JsonConvert.DeserializeObject("{ 'uploaded': 0, 'error': { 'message': \"" + DimensionErrorMessage + "\"}}"); return Json(stuff); } if (upload.Length > 500 * 1024) { var LengthErrorMessage = "The file is too big. Maximum file size is 5mb"; dynamic stuff = JsonConvert.DeserializeObject("{ 'uploaded': 0, 'error': { 'message': \"" + LengthErrorMessage + "\"}}"); return Json(stuff); } var directory = Path.Combine(_env.WebRootPath, "uploads", admin.League.Id.ToString(), "pages"); var path = Path.Combine(directory, fileName); if (!Directory.Exists(directory)) { var mkdir = Directory.CreateDirectory(directory); } try { using (var stream = new FileStream(path, FileMode.Create)) { await upload.CopyToAsync(stream); } } catch (Exception ex) { var exception = ex.Message; } var url = $"{"/uploads/" + admin.League.Id.ToString() + "/pages/"}{fileName}"; var successMessage = "File is uploaded successfully"; var success = JsonConvert.DeserializeObject("{ 'uploaded': 1,'fileName': \"" + fileName + "\" ,'url': \"" + url + "\" , 'error': { 'message': \"" + successMessage + "\"}}"); return Json(success); }
调试断点处的对象值

浏览器实际响应

问题原因及解决方法
问题源于你用JsonConvert.DeserializeObject生成dynamic对象后,ASP.NET Core默认的System.Text.Json序列化器无法正确处理Newtonsoft.Json创建的动态对象,导致最终返回空列表。
方案1:使用强类型对象构建响应
定义符合CKEditor要求的响应类,避免使用dynamic:
public class CKEditorUploadResponse { public int uploaded { get; set; } public string fileName { get; set; } public string url { get; set; } public CKEditorError error { get; set; } } public class CKEditorError { public string message { get; set; } }
修改成功响应代码:
var success = new CKEditorUploadResponse { uploaded = 1, fileName = fileName, url = url, error = new CKEditorError { message = successMessage } }; return Json(success);
错误响应部分同样替换为强类型对象,比如非图片的情况:
return Json(new CKEditorUploadResponse { uploaded = 0, error = new CKEditorError { message = NotImageMessage } });
方案2:配置ASP.NET Core使用Newtonsoft.Json序列化
若要继续使用dynamic,需添加Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet包,然后在Program.cs中配置:
builder.Services.AddControllersWithViews() .AddNewtonsoftJson();
这样ASP.NET Core会用Newtonsoft.Json处理序列化,能正确识别之前的动态对象。
额外优化点
upload.Length <= 0时返回null不合理,建议返回标准错误响应:return Json(new CKEditorUploadResponse { uploaded = 0, error = new CKEditorError { message = "上传文件为空" } });- 图片流未释放,用
using包裹:using (Image image = Image.FromStream(upload.OpenReadStream())) { int width = image.Width; int height = image.Height; // 尺寸判断逻辑 } - 异常捕获后需返回错误响应,不要仅记录消息:
catch (Exception ex) { return Json(new CKEditorUploadResponse { uploaded = 0, error = new CKEditorError { message = $"文件上传失败:{ex.Message}" } }); }
内容的提问来源于stack exchange,提问作者Matthew Warr
相关产品推荐
相关产品推荐

