2011-04-29 137 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