ASP.NET MVC中通过JQuery AJAX上传Excel后MyController2无法获取文件如何解决
问题原因
你碰到的问题由两个错误导致:
- 发送邀请的AJAX请求写法错误:无法通过JSON序列化传输二进制文件,所以MyController2里
Request.Files.Count为0 HttpPostedFileBase对象和当前请求的输入流绑定,请求结束后流会被自动释放,直接存到TempData里下次读取必然拿不到有效内容,这就是你看到ContentLength为0的原因
解决方案
这里提供两种可行方案,按需选择即可:
方案1:发送邀请时直接传文件(推荐,逻辑更简单)
修改前端SendInvite方法,不要把参数转成JSON,把表单字段和文件都放到FormData里传输,配置和之前上传校验的AJAX保持一致:
function SendInvite() { // 先完成页面其他输入项校验 var formData = new FormData(); // 追加Excel文件 var excelFile = document.getElementById('ExcelFile'); if (excelFile.files.length > 0) { formData.append('excelFile', excelFile.files[0]); } // 追加MyModel的所有字段,示例:假设MyModel有Title、Contact两个字段 formData.append('myModel.Title', $('#titleInput').val()); formData.append('myModel.Contact', $('#contactInput').val()); $.ajax({ type: "POST", url: "你的MyController2接口地址", data: formData, contentType: false, // 必须设为false,让浏览器自动设置正确的请求头 processData: false, // 必须设为false,不要让Jquery处理FormData dataType: "json", success: function (data) { // 成功处理逻辑 }, error: function (data) { // 错误处理逻辑 } }); }
修改后MyController2可以直接拿到文件:
public JsonResult MyController2(MyModel myModel, HttpPostedFileBase excelFile) { // 这里excelFile已经可以正常读取,Request.Files也有值 // 后续发邮件等逻辑 }
方案2:校验后存储文件字节到TempData(适合需要保留校验结果的场景)
不要直接存HttpPostedFileBase,把文件转成字节数组存储到TempData,读取时直接用字节数组即可:
第一步:修改校验接口的存储逻辑
[HttpPost] public JsonResult MyController(HttpPostedFileBase excelFile) { if (Request.Files.Count > 0) { excelFile = Request.Files[0]; var result = // 你的文件校验逻辑 if(result.校验成功) { // 把文件流转成字节数组存储 using (var reader = new BinaryReader(excelFile.InputStream)) { TempData["ExcelBytes"] = reader.ReadBytes(excelFile.ContentLength); } // 额外存储文件名、格式,后续发附件会用到 TempData["ExcelFileName"] = excelFile.FileName; TempData["ExcelContentType"] = excelFile.ContentType; } return Json(result); } return null; }
第二步:修改发送邀请接口的读取逻辑
public JsonResult MyController2(MyModel myModel) { byte[] excelBytes = TempData["ExcelBytes"] as byte[]; string fileName = TempData["ExcelFileName"] as string; string contentType = TempData["ExcelContentType"] as string; if(excelBytes != null && excelBytes.Length > 0) { // 这里已经拿到完整的Excel文件内容,发邮件时直接把这个字节数组作为附件即可 } // 后续业务逻辑 }
注意事项
- TempData默认读取一次后就会被销毁,如果需要多次读取可以调用
TempData.Keep("ExcelBytes")保留数据 - 如果Excel文件比较大,建议校验后先存到服务器临时目录,把路径存到TempData,发完邮件再删除临时文件,避免占用服务端内存
内容的提问来源于stack exchange,提问作者Viveka
相关产品推荐
相关产品推荐

