2011-04-29 70 views
3

我有一个MVC3应用程序,从用户的硬盘上传文件并对其进行操作。一个要求是文件扩展名应该是.xls(或xlsx)。在ASP.NET MVC3与C#中的远程文件扩展名验证?

我想验证文件名,但我想知道什么是重用性能方面的最佳选择(当然,最好的编码实践)。

我有以下索引视图:

@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>   
    } 

由控制器操作方法调用指数

public ActionResult Index() 
{ 
    return View("Index"); 
} 

而且用户响应由指数操作方法处理(HttpPost):

[HttpPost] 
public ActionResult Index(HttpPostedFileBase file) 
{ 
    FileServices lfileServices = new FileServices(); 
    var lfilePath = lfileServices.UploadFile(file, "~/App_Data/uploads"); 
    //Manipulation; 
} 

现在我可以在FileServices中使用Path.GetExtension(filename)来获取扩展名,然后执行检查,但是它会在上传完成后立即执行。

我想这样做,一旦用户尝试上传文件。唯一出现在我脑海的是创建一个Model(或更好的ViewModel)并使用远程验证DataAnnotations

我看到了Scott Hanselman的一次演示,但似乎他并不真正舒适,因为应用程序正在编译,但没有执行检查。

有没有人为了执行这样的远程验证或任何其他解决方案(例如jQuery)的好方法?

感谢

弗朗西斯

回答

5

你可以这样做使用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并将其上传。通过查看一些已知的字节序列,可以在服务器上使用试探法来尝试猜测实际的文件类型。


UPDATE:

实例与远程AJAX验证(由于意见需求,我不建议这样做虽然)。你可以使用优秀的jquery.validate plugin,它与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); 
} 
+0

@Darin季米特洛夫:谢谢您的回答。你怎么看待调用动作方法而不是在jQuery中执行检查? – CiccioMiami 2011-04-29 10:57:43

+0

@Francesco,我没有看到需要。如果这个动作所能做的只是验证扩展名,这可以在客户端完成。为什么浪费带宽? – 2011-04-29 11:07:09

+0

@Darin Dimitrov:例如,如果您概括了大小写,并且您希望在具有不同文件类型的其他应用程序中重用该功能。 – CiccioMiami 2011-04-29 11:22:21