我有一个MVC3应用程序,它从用户的硬盘驱动器上传文件并对其进行操作。一个要求是文件扩展名应该是.xls(或xlsx)。
我想验证文件名,但我想知道在可重用性和性能(当然还有最佳编码实践)方面的最佳选择是什么。
我有以下索引视图:
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<br />
<p><input type="file" id="file" name="file" size="23"/></p><br />
<p><input type="submit" value="Upload file" /></p>
}
由控制器动作方法调用Index:
public ActionResult Index()
{
return View("Index");
}
用户响应由Index action方法(HttpPost)处理:
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
FileServices lfileServices = new FileServices();
var lfilePath = lfileServices.UploadFile(file, "~/App_Data/uploads");
//Manipulation;
}
现在我可以在FileServices中使用Path.GetExtension(filename)
来获取扩展名,然后执行检查,但它将在上传完成后执行。
我想在用户尝试上传文件时执行此操作。我唯一想到的是创建一个模型(或更好的ViewModel),并使用远程验证从DataAnnotations。
我看到了Scott Hanselman的现场演示,但他似乎对此并不满意,因为应用程序正在编译,但没有执行检查。
有没有人有好的方法来执行这种远程验证或任何其他解决方案(例如jQuery)?
感谢Francesco
你可以使用javascript:
$(function () {
$('form').submit(function () {
var selectedFile = $('#file').val();
var matches = selectedFile.match(/.(xlsx?)$/i);
if (matches == null) {
alert('please select an Excel file');
return false;
}
return true;
});
});
当然,在任何情况下,这并不能免除你在服务器上执行相同检查的义务,因为如果客户端没有启用javascript,这将是唯一的方法。即使这样也不是100%可靠,因为没有什么可以阻止用户将任何垃圾文件重命名为.xls
并上传它。启发式可以在服务器上使用,通过查看一些已知的字节序列来尝试猜测实际的文件类型。
更新:
远程AJAX验证的示例(由于注释中的要求,我不推荐这样做)。您可以使用出色的jquery。validate插件,顺便说一下,它是与ASP捆绑在一起的。. NET MVC 3:
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" id="file" name="file" size="23" data-remote-val-url="@Url.Action("CheckExtension")"/>
<br />
<input type="submit" value="Upload file" />
}
<script type="text/javascript">
$('form').validate({
rules: {
file: {
remote: $('#file').data('remote-val-url')
}
},
messages: {
file: {
remote: 'Please select an Excel file'
}
}
});
</script>
在服务器端:
public ActionResult CheckExtension(string file)
{
var extension = Path.GetExtension(file ?? string.Empty);
var validExtensions = new[] { ".xls", ".xlsx" };
var isValid = validExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
return Json(isValid, JsonRequestBehavior.AllowGet);
}