Загрузка и получение изображений ASP.NET Core MVC
Изображения неизбежны почти во всех приложениях. Ранее мы реализовали CRUD-операцию с обычной формой без файла для загрузки. Когда у нас есть форма с загрузчиком файлов, дополнительных процедур немного. Итак, давайте посмотрим, как загружать и получать изображения в ASP.NET Core MVC .
Обсуждаемые подтемы:
- Разработка формы MVC для загрузки изображения
- Отправить форму обработки изображения
- Сохраните изображение в файл сервера.
- Получить загруженное обратно в представление.
- Удалить запись изображения и файл.
Создать проект ASP.NET Core MVC
В Visual Studio 2019 выберите «Файл» > «Создать» > «Проект» (Ctrl + Shift + N). Выберите шаблон веб-приложения Asp.Net Core.
После того, как вы укажете название проекта и местоположение. Откроется новое окно следующего содержания: выберите «Веб-приложение (MVC)» и снимите флажок «Конфигурация HTTPS». Вышеуказанные шаги создадут новый проект ASP.NET Core MVC.
Определите класс модели
Давайте создадим базу данных с помощью Entity Framework Core. Для этого мы должны установить соответствующие пакеты NuGet. Поэтому щелкните правой кнопкой мыши проект в обозревателе решений, выберите «Управление пакетами NuGet», на вкладке «Обзор» найдите и установите соответствующие следующие 3 пакета.
Теперь давайте определим класс модели БД ImageModel
в новой папке — Models
.
//File : /Models/ImageModel.cs
public class ImageModel
{
[Key]
public int ImageId { get; set; }
[Column(TypeName ="nvarchar(50)")]
public string Title { get; set; }
[Column(TypeName = "nvarchar(100)")]
[DisplayName("Image Name")]
public string ImageName { get; set; }
[NotMapped]
[DisplayName("Upload File")]
public IFormFile ImageFile { get; set; }
}
Помимо первичного ключа, у нас есть столбцы Title
, которые ImageName.
ImageName
используются для сохранения имени изображения. IFormFile
свойство ImageFile
является NotMapped
свойством, что означает, что в базе данных не будет соответствующего столбца таблицы, который просто используется для получения опубликованного файла изображения во время отправки формы, например, свойство модели представления.
Настройка базы данных
Теперь давайте определим класс DbContext ImageDbContext
для создания и управления базой данных.
//File : /Models/ImageDbContext.cs
public class ImageDbContext:DbContext
{
public ImageDbContext(DbContextOptions<ImageDbContext> options):base(options)
{ }
public DbSet<ImageModel> Images { get; set; }
}
Согласно приведенному выше классу DbContext, после миграции БД будет таблица Images
для сохранения записей, соответствующих классу модели ImageModel
. Для взаимодействия с БД нам нужен экземпляр класса DbContext ImageDbContext
. Для этого мы немного воспользуемся внедрением зависимостей ASP.NET Core.
Перед этим давайте поговорим о параметре конструктора класса options
типа DbContextOptions
. В этот параметр опций мы должны передать следующую информацию.
- Поставщик базы данных: укажите базу данных, которую мы хотим использовать, будь то SQL Server или MySQL и т. д.
- Местоположение базы данных: строка подключения к базе данных, которую мы хотим создать.
Сохраним строку подключения в appsettings.json
файле.
{
....
"ConnectionStrings": {
"DevConnection": "Server=(local)\\sqlexpress;Database=ImageDB;Trusted_Connection=True;MultipleActiveResultSets=True;"
}
}
Теперь позвольте мне показать вам, как создать экземпляр DbContext
с внедрением зависимостей. Просто обновите Startup
метод класса ConfigureServices
, как показано ниже.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDbContext<PaymentDetailContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DevConnection")));
}
Здесь мы вызвали AddDbContext
метод для внедрения экземпляра PaymentDetailContext
. Здесь, чтобы установить SQL Server в качестве DbProvider, UseSqlServer
функция вызывается с указанной выше строкой подключения. Как работает эта инъекция зависимостей? которые мы можем обсудить после создания контроллера MVC.
Мы сделали все для базы данных, теперь давайте сделаем миграцию. Для этого выберите проект в обозревателе решений, затем перейдите в Инструменты > Диспетчер пакетов NuGet > Консоль диспетчера пакетов. затем выполните следующие команды одну за другой.
Add-Migration "InitialCreate"
Update-Database
После успешной миграции в соответствии со строкой подключения ImageDB
будет создана новая база данных с новой таблицей Images
, соответствующей классу модели.
Создайте контроллер изображений MVC с действиями CRUD
Чтобы обновлять и извлекать изображения, давайте создадим контроллер MVC. щелкните правой кнопкой мыши папку «Контроллеры» «Добавить»> «Контроллер», выберите «Контроллер MVC с представлениями с использованием шаблона Entity Framework». ImageController
будет создан с помощью ImageModel
и ImageDbContext
.
С помощью Scaffolding Mechanism будет создан новый контроллер с необходимыми методами действий для всех операций CRUD.
public class ImageController : Controller
{
private readonly ImageDbContext _context;
public ImageController(ImageDbContext context)
{
_context = context;
}
// GET: Image
public async Task<IActionResult> Index()
{ ... }
// GET: Image/Create
public IActionResult Create()
{ ... }
// POST: Image/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ImageId,Title,ImageName")] ImageModel imageModel)
{ ... }
// GET: Image/Delete/5
public async Task<IActionResult> Delete(int? id)
{ ... }
// POST: Image/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{ ... }
}
Теперь давайте обсудим, как внедрение зависимостей ASP.NET Core помогает этому контроллеру взаимодействовать с БД. Этот ImageController
конструктор имеет параметр ImageDbContext
(который равен _context
), ASP.NET Core автоматически вставит тот же экземпляр класса в параметр в качестве его значения. Нам не нужно создавать экземпляр контекста в каждом из контроллеров MVC, если у контроллера есть параметр конструктора типа ImageDbContext
. Теперь остальные методы действия могут взаимодействовать с БД, используя этот внедренный DbContext.
В приведенном выше контроллере мы показали методы действий, необходимые для демонстрации загрузки изображения. есть и другие методы действия, но они не используются в этом проекте. Давайте откроем этот проект в вашем браузере, перейдите в «Отладка»> «Начать без отладки».
Теперь, если вы перейдете по URL: /Image/Create
, вы увидите форму с элементами управления вводом, соответствующими каждому свойству модели, кроме ImageFile
. поэтому мы должны заменить ImageName
элементы управления вводом на загрузчик изображения/файла, соответствующий ImageFile
свойству. Ведь Create.cshtml
должно выглядеть вот так.
//File: /Views/Image/Create.cshtml
@model ImageUpload.Models.ImageModel
@{ ViewData["Title"] = "Create"; }
<h1>Create</h1>
<h4>ImageModel</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ImageFile" class="control-label"></label>
<input asp-for="ImageFile" accept="image/*" />
<span asp-validation-for="ImageFile" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
С помощью accept
атрибута мы ограничили загрузчик только файлами изображений. Если в нашу форму загружен файл, мы должны установить атрибут формы enctype
как « multipart/form-data». Если вы перезагрузите страницу, вы увидите новую форму, подобную этой.
Эта форма будет передана Create
методу действия типа POST
. там также мы должны внести некоторые изменения, как показано ниже.
using Microsoft.AspNetCore.Hosting;
public class ImageController : Controller
{
private readonly IWebHostEnvironment _hostEnvironment;
public ImageController(..., IWebHostEnvironment hostEnvironment)
{
...
this._hostEnvironment = hostEnvironment;
}
...
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ImageId,Title,ImageFile")] ImageModel imageModel)
{
if (ModelState.IsValid)
{
//Save image to wwwroot/image
string wwwRootPath = _hostEnvironment.WebRootPath;
string fileName = Path.GetFileNameWithoutExtension(imageModel.ImageFile.FileName);
string extension = Path.GetExtension(imageModel.ImageFile.FileName);
imageModel.ImageName=fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
string path = Path.Combine(wwwRootPath + "/Image/", fileName);
using (var fileStream = new FileStream(path,FileMode.Create))
{
await imageModel.ImageFile.CopyToAsync(fileStream);
}
//Insert record
_context.Add(imageModel);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(imageModel);
}
....
}
Как вы знаете, это суть этой статьи. В метод действия мы привязали свойства модели – ImageId
и Title
( ImageFile
не ImageName
).
Прежде всего, мы сохраняем изображение в папку wwwroot/Image. Для этого нам нужен физический путь до папки wwwroot, для этого мы внедрили IWebHostEnvironment
свойство, подобное нашему DbContext. Генерируется уникальное пользовательское имя для файла изображения, чтобы избежать дублирования файлов изображений. Используя FileStream
объект, мы можем сохранить изображение в images
папку с произвольным именем.
В качестве второго шага мы вставляем детали изображения с пользовательским именем изображения в базу данных. Теперь вы можете попробовать загрузить изображение после перестроения решения.
После успешного завершения загрузки изображения вы будете перенаправлены в индексное представление. где вставленные записи будут перечислены из таблицы базы данных – Images
.
Получить и удалить изображение
Если вы нажмете гиперссылку «Удалить», Delete
откроется представление с отображением соответствующих сведений о записи. Чтобы отобразить загруженное изображение обратно в представление, мы должны внести несколько изменений в файл Views/Image/Delete.cshtml
.
@model ImageUpload.Models.ImageModel
@{ ViewData["Title"] = "Delete"; }
<h1>Delete</h1>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>ImageModel</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.ImageName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.ImageName)
</dd>
<dt class="col-sm-2">
Uploaded Image
</dt>
<dd class="col-sm-10">
<img decoding="async" src="@("~/image/"+Model.ImageName)" asp-append-version="true" width="250px" height="250px"/>
</dd>
</dl>
<form asp-action="Delete">
<input type="hidden" asp-for="ImageId" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-action="Index">Back to List</a>
</form>
</div>
Основная цель представления — подтвердить операцию удаления. с атрибутом img
атрибута управления src
используется относительный путь полученного изображения. Чтобы добавить базовый путь, мы можем установить для атрибута значение asp-append-version
true .
Если вы подтвердите эту операцию удаления, она дойдет до DeleteConfirmed
метода действия типа POST
. по умолчанию он запрограммирован на удаление соответствующей записи. Наряду с этим мы должны удалить соответствующий файл изображения из папки «изображение». для этого мы можем обновить метод действия.
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var imageModel = await _context.Images.FindAsync(id);
//delete image from wwwroot/image
var imagePath = Path.Combine(_hostEnvironment.WebRootPath,"image",imageModel.ImageName);
if (System.IO.File.Exists(imagePath))
System.IO.File.Delete(imagePath);
//delete the record
_context.Images.Remove(imageModel);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
Это все, что касается загрузки и извлечения изображений в ASP.NET Core MVC. Если вы хотите реализовать остальную часть операции CRUD — редактирование, вы можете ознакомиться с этой статьей — ASP.NET Core MVC CRUD с Entity Framework.
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.