为什么ASP.NET MVC返回模型到视图时文件上传input的值为null?
问题成因
- 首先是浏览器的强制安全限制:所有主流浏览器都禁止代码主动设置
<input type="file">控件的value属性,避免恶意网站未经用户许可窃取本地文件。哪怕服务端回传了完整的HttpPostedFileBase对象,也无法通过任何前端逻辑给文件上传框回填值,这是不可突破的沙箱规则。 - ASP.NET MVC本身的渲染逻辑也不会处理文件上传控件的回发回填:不管是手写的原生file input,还是用
Html.TextBoxFor强类型绑定的控件,渲染时都会忽略模型中HttpPostedFileBase类型的属性值,不会生成对应的value属性,所以控件会显示为空。
解决方案
根据业务场景选择对应方案即可:
- 无需用户重复上传的场景
把首次上传的文件临时存储在服务端(临时目录、Session、分布式缓存都可),生成唯一的文件标识返回给视图,视图侧判断已存在上传文件时,优先展示已上传的文件信息,保留上传框作为替换入口:
后端逻辑调整:第二次提交时如果新的@* 视图代码改造 *@ @using (Html.BeginForm("UploadBook", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.TextBoxFor(m => m.Author) <br /><br /> @if (Model.Book != null && Model.Book.ContentLength > 0) { <p>已上传文件:@Model.Book.FileName (大小:@(Model.Book.ContentLength/1024)KB)</p> @Html.Hidden("SavedFileId", 你生成的临时文件唯一ID) <span>如需替换请重新选择:</span> } <input type="file" name="Book" /><br /> <input type="submit" value="提交"/> }model.Book为空但存在SavedFileId,直接读取之前存储的临时文件即可,无需用户重新上传。 - 要求每次提交必须重新上传的场景
直接给文件上传控件加必填验证即可,前端加required属性,后端补充ModelState校验逻辑,回发时如果文件为空抛出提示要求用户重新选择:<input type="file" name="Book" required /><br />
注意:不要尝试通过JavaScript给文件上传控件赋值,所有这类操作都会被浏览器拦截,没有任何可落地的绕过方案。
内容的提问来源于stack exchange,提问作者Ahmed Saif
相关产品推荐
相关产品推荐

