Загрузка файлов в ASP.NET MVC 3: как правильно реализовать?
Основная причина: несоответствие имени поля и модели
Ваша главная ошибка — в представлении вы используете name="File", а в модели свойство называется File. Это правильно, но важно: в Html.BeginForm вы забыли указать enctype = "multipart/form-data" в правильном месте. У вас он есть, но давайте проверим весь код.
На самом деле, если model.File приходит null, скорее всего проблема в том, что вы используете @Html.TextBoxFor(m => m.FileName) без enctype на форме, либо форма не отправляется как multipart. Убедитесь, что ваш BeginForm выглядит так:
@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.TextBoxFor(m => m.FileName)
<input type="file" name="File" id="File" />
<input type="submit" value="Загрузить" />
}
Полный рабочий пример
Вот проверенный код для ASP.NET MVC 3:
// Модель
public class UploadViewModel
{
public string FileName { get; set; }
public HttpPostedFileBase UploadedFile { get; set; } // Переименуйте, чтобы избежать путаницы
}
// Контроллер
[HttpPost]
public ActionResult Upload(UploadViewModel model)
{
if (model.UploadedFile != null && model.UploadedFile.ContentLength > 0)
{
// Проверка расширения
var allowedExtensions = new[] { ".jpg", ".png", ".pdf", ".docx" };
var fileExtension = Path.GetExtension(model.UploadedFile.FileName).ToLower();
if (!allowedExtensions.Contains(fileExtension))
{
ViewBag.Error = "Недопустимый формат файла.";
return View();
}
// Проверка размера (например, не более 5 МБ)
if (model.UploadedFile.ContentLength > 5 * 1024 * 1024)
{
ViewBag.Error = "Файл слишком большой (макс. 5 МБ).";
return View();
}
// Генерация уникального имени, чтобы избежать конфликтов
var uniqueFileName = Guid.NewGuid().ToString() + fileExtension;
var savePath = Path.Combine(Server.MapPath("~/uploads"), uniqueFileName);
model.UploadedFile.SaveAs(savePath);
ViewBag.Message = $"Файл '{model.UploadedFile.FileName}' успешно загружен как '{uniqueFileName}'.";
}
else
{
ViewBag.Error = "Файл не выбран или пуст.";
}
return View();
}
Как загрузить несколько файлов
Для множественной загрузки используйте IEnumerable<HttpPostedFileBase>:
// В модели
public IEnumerable<HttpPostedFileBase> Files { get; set; }
// В представлении
<input type="file" name="Files" multiple />
// В контроллере
[HttpPost]
public ActionResult UploadMultiple(IEnumerable<HttpPostedFileBase> files)
{
foreach (var file in files)
{
if (file != null && file.ContentLength > 0)
{
// обработка каждого файла
}
}
}
Важные моменты
- enctype — обязателен для загрузки файлов. Без него файлы не передаются.
- Размер файла — по умолчанию в ASP.NET MVC 3 лимит 4 МБ. Чтобы увеличить, добавьте в
web.config:<system.web> <httpRuntime maxRequestLength="10240" /> <!-- 10 МБ --> </system.web> - Безопасность — всегда проверяйте расширение и размер на сервере, не полагайтесь только на клиентскую проверку.
- Путь сохранения — используйте
Server.MapPathдля преобразования виртуального пути в физический.
Альтернативный подход: использование Ajax для асинхронной загрузки
Если вы хотите загружать файлы без перезагрузки страницы, можно использовать jQuery и Ajax. Это улучшает пользовательский опыт.
// Представление с формой и скриптом
@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data", id = "uploadForm" }))
{
<input type="file" name="File" id="fileInput" />
<input type="submit" value="Загрузить" />
}
<div id="result"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$('#uploadForm').submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: '@Url.Action("Upload", "Home")',
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function (data) {
$('#result').html(data.Message);
},
error: function () {
$('#result').html('Ошибка загрузки.');
}
});
});
</script>
В контроллере оставьте тот же метод Upload, но верните JSON вместо View:
[HttpPost]
public ActionResult Upload(UploadViewModel model)
{
// ... проверки, как в первом ответе ...
if (success)
return Json(new { Message = "Файл загружен." });
else
return Json(new { Message = "Ошибка." });
}
Этот подход позволяет показывать сообщения без перезагрузки страницы и легко обрабатывать множественные файлы.
Ответов пока нет.
Войдите чтобы оставить ответ