public async Task <IActionResult> ViewGallery(Guid galleryId, string imageToDeleteName = null) { // Если есть изображение, которое надо удалить, заходим в тело условия if (imageToDeleteName != null) { // Создаем экземпляр класса картинки и присваиваем ему данные из БД GalleryImage galleryImage = await _websiteDB.GalleryImages.FirstOrDefaultAsync(i => i.ImageName == imageToDeleteName); // Делаем еще одну проверку. Лучше перебдеть. Если все ок, заходим в тело условия и удаляем изображения if (galleryImage != null) { // Исходные (полноразмерные) изображения FileInfo imageOriginal = new FileInfo(_appEnvironment.WebRootPath + galleryImage.ImagePathOriginal); if (imageOriginal.Exists) { imageOriginal.Delete(); } // И их уменьшенные копии FileInfo imageScaled = new FileInfo(_appEnvironment.WebRootPath + galleryImage.ImagePathScaled); if (imageScaled.Exists) { imageScaled.Delete(); } // Удаляем информацию об изображениях из БД и сохраняем _websiteDB.GalleryImages.Remove(galleryImage); await _websiteDB.SaveChangesAsync(); } } // Выбираем галерею из БД Gallery gallery = await _websiteDB.Galleries.FirstOrDefaultAsync(g => g.Id == galleryId); if (gallery != null) { // Создаем список изображений из БД, закрепленных за выбранной галереей List <GalleryImage> images = await _websiteDB.GalleryImages.Where(i => i.GalleryId == galleryId).OrderByDescending(i => i.ImageDate).ToListAsync(); // Создаем модель для передачи в представление и присваиваем значения ViewGalleryViewModel model = new ViewGalleryViewModel() { GalleryTitle = gallery.GalleryTitle, GalleryDescription = gallery.GalleryDescription, GalleryImages = images, // Скрытые поля GalleryId = galleryId, GalleryDate = gallery.GalleryDate, UserName = gallery.GalleryUserName, ImagesCount = images.Count }; // Передаем модель в представление return(View(model)); } else { return(Redirect("/Main/PageNotFound")); } }
public async Task <IActionResult> ViewGallery(ViewGalleryViewModel model, IFormFileCollection uploads) { // Настройки галереи SettingsGallery settings = await _websiteDB.SettingsGallery.FirstAsync(); int imageSize = 1048576 * settings.MaxImageSize; int imagesPerGallery = settings.ImagesPerGallery; // Выбираем все изображения, находящиеся в данной галерее List <GalleryImage> images = await _websiteDB.GalleryImages.Where(i => i.GalleryId == model.GalleryId).OrderByDescending(i => i.ImageDate).ToListAsync(); // Проверяем, не превышает ли количество загружаемых изображений допустимый лимит if (uploads.Count > imagesPerGallery - images.Count) { ModelState.AddModelError("GalleryImage", $"Превышен лимит изображений для галереи."); //ModelState.AddModelError("GalleryImage", $"Вы пытаетесь загрузить {uploads.Count} изображений. Лимит галереи {imagesPerGallery} изображений. Вы можете загрузить еще {imagesPerGallery - images.Count} изображений."); } // Если всё в порядке, заходим в ELSE else { // Проверяем, чтобы размер файлов не превышал заданный объем foreach (var file in uploads) { if (file == null || file.Length == 0) { ModelState.AddModelError("GalleryImage", $"Произошла ошибка при обработке файла \"{file.FileName}\"."); break; } if (file.Length > imageSize) { ModelState.AddModelError("GalleryImage", $"Файл \"{file.FileName}\" превышает установленный лимит {settings.MaxImageSize}MB."); break; } } } // Если все в порядке, заходим в тело условия if (ModelState.IsValid) { // Далее начинаем обработку загружаемых изображений List <GalleryImage> galleryImages = new List <GalleryImage>(); foreach (var uploadedImage in uploads) { // Создаем новый объект класса FileInfo из полученного изображения для дальнейшей обработки FileInfo imgFile = new FileInfo(uploadedImage.FileName); // Приводим расширение к нижнему регистру (если оно было в верхнем) string imgExtension = imgFile.Extension.ToLower(); // Генерируем новое имя для файла string newFileName = Guid.NewGuid() + imgExtension; // Пути сохранения файла string originalDirectory = "/uploadedfiles/gallery/images/original/"; string scaledDirectory = "/uploadedfiles/gallery/images/scaled/"; string pathOriginal = originalDirectory + newFileName; // изображение исходного размера string pathScaled = scaledDirectory + newFileName; // уменьшенное изображение // Если такой директории не существует, то создаем её if (!Directory.Exists(_appEnvironment.WebRootPath + originalDirectory)) { Directory.CreateDirectory(_appEnvironment.WebRootPath + originalDirectory); } if (!Directory.Exists(_appEnvironment.WebRootPath + scaledDirectory)) { Directory.CreateDirectory(_appEnvironment.WebRootPath + scaledDirectory); } // В операторе try/catch делаем уменьшенную копию изображения. // Если входным файлом окажется не изображение, нас перекинет в блок CATCH и выведет сообщение об ошибке try { // Создаем объект класса SixLabors.ImageSharp.Image и грузим в него полученное изображение using (Image image = Image.Load(uploadedImage.OpenReadStream())) { // Создаем уменьшенную копию и обрезаем её var clone = image.Clone(x => x.Resize(new ResizeOptions { Mode = ResizeMode.Crop, Size = new Size(300, 169) })); // Сохраняем уменьшенную копию await clone.SaveAsync(_appEnvironment.WebRootPath + pathScaled, new JpegEncoder { Quality = settings.ImageResizeQuality }); // Сохраняем исходное изображение await image.SaveAsync(_appEnvironment.WebRootPath + pathOriginal); } } // Если вдруг что-то пошло не так (например, на вход подало не картинку), то выводим сообщение об ошибке catch { // Создаем сообщение об ошибке для вывода пользователю ModelState.AddModelError("GalleryImage", $"Файл {uploadedImage.FileName} имеет неверный формат."); // Удаляем только что созданные файлы (если ошибка возникла не на первом файле и некоторые уже были загружены на сервер) foreach (var image in galleryImages) { // Исходные (полноразмерные) изображения FileInfo imageOriginal = new FileInfo(_appEnvironment.WebRootPath + image.ImagePathOriginal); if (imageOriginal.Exists) { imageOriginal.Delete(); } // И их уменьшенные копии FileInfo imageScaled = new FileInfo(_appEnvironment.WebRootPath + image.ImagePathScaled); if (imageScaled.Exists) { imageScaled.Delete(); } } // Возвращаем модель с сообщением об ошибке в представление return(View(model)); } // Создаем объект класса GalleryImage со всеми параметрами GalleryImage galleryImage = new GalleryImage() { Id = Guid.NewGuid(), ImageName = newFileName, ImagePathOriginal = pathOriginal, ImagePathScaled = pathScaled, GalleryId = model.GalleryId, ImageDate = DateTime.Now }; // Добавляем объект galleryImage в список galleryImages galleryImages.Add(galleryImage); } // Если в процессе выполнения не возникло ошибок, сохраняем всё в БД if (galleryImages != null && galleryImages.Count > 0) { await _websiteDB.GalleryImages.AddRangeAsync(galleryImages); await _websiteDB.SaveChangesAsync(); } // Выводим обновленную модель в представление return(RedirectToAction("ViewGallery", "Gallery", new { galleryId = model.GalleryId })); } // В случае, если произошла ошибка валидации, требуется заново присвоить список изображений и счетчик для возвращаемой модели // При перегонке модели из гет в пост, теряется список с изображениями. Причина пока не ясна, поэтому сделал такой костыль // Счетчик соответственно тоже обнулялся, поэтому его тоже приходится переназначать заново model.GalleryImages = images; model.ImagesCount = images.Count; // Возврат модели в представление в случае, если запорится валидация return(View(model)); }