Перевод: Phil Haack – Uploading a File (Or Files) With ASP.NET MVC
Я хотел убедиться в том как осуществляется загрузка файла или набора файлов с помощью ASP.NET MVC и первым результатом поиска по фразе “uploading a file with asp.net mvc” была статья в блоге Скотта Хансельмана.
Его статья очень подробна и помогает понять что происходит под капотом. У меня есть только одна претензия к коду, он может стать проще, потому что с тех пор мы доработали ASP.NET MVC 2. Я пишу эту статью в блог в надежде скинуть его статью с первого места.
Загрузка одиночного файла
Давайте начнем с создания представления. Вот форма, которая будет возвращать результат в текущий метод контроллера.
<form action="" method="post" enctype="multipart/form-data"> <label for="file">Filename:</label> <input type="file" name="file" id="file" /> <input type="submit" /> </form>
Вот метод контроллера, в который будет возвращаться результат из представления и сохраняться в директорию “uploads” на сервере.
[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
if (file.ContentLength > 0) {
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
Обратите внимание, аргумент метода является экземпляром типа HttpPostedFileBase. ASP.NET MVC 2 представляет новую возможность – провайдеры значений (value providers), о которых я уже писал ранее.
“В то время как model binders используются для связывания входных данных с объектной моделью, провайдеры значений представляют абстракцию для самих входных данных.”
В данном случае провайдер значений по умолчанию называется HttpFileCollectionValueProvider, который предоставляет загруженные файлы в model binder. Также обратите внимание на имя аргумента – file, оно совпадает с именем переданного файла. Это очень важно что бы model binder загруженного файла совпадал с аргументом метода контроллера.
Загрузка нескольких файлов
В данном сценарии мы хотим загрузить набор файлов. Мы просто можем иметь несколько полей с одинаковыми именами для выбора файла.
<form action="" method="post" enctype="multipart/form-data"> <label for="file1">Filename:</label> <input type="file" name="files" id="file1" /> <label for="file2">Filename:</label> <input type="file" name="files" id="file2" /> <input type="submit" /> </form>
Теперь мы можем просто подкрутить наш метод контроллера, что бы принимать аргументы типа IEnumerable. Снова обратите внмание, что имя аргумента должно совпадать с именем передаваемого из формы поля.
[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files) {
foreach (var file in files) {
if (file.ContentLength > 0) {
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/uploads"), fileName);
file.SaveAs(path);
}
}
return RedirectToAction("Index");
}
Да, это очень просто.
