How to upload files and images in .net core

    public interface IImageService
    {
        Task<string> UploadImageAsync(IFormFile file, string folder);
        Task<bool> DeleteImageAsync(string imagePath);
        bool IsValidImage(IFormFile file);
        Task<string> ResizeImageAsync(string imagePath, int width, int height);
    }

    public class ImageService : IImageService
    {
        private readonly IWebHostEnvironment _environment;
        private readonly ILogger<ImageService> _logger;
        private readonly string[] _allowedExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".webp" };
        private readonly long _maxFileSize = 5 * 1024 * 1024; // 5MB


        public ImageService(IWebHostEnvironment environment, ILogger<ImageService> logger)
        {
            _environment = environment;
            _logger = logger;
        }


        public async Task<string> UploadImageAsync(IFormFile file, string folder)
        {
            if (file == null || file.Length == 0)
                throw new ArgumentException("No file provided");


            if (!IsValidImage(file))
                throw new ArgumentException("Invalid image file");


            // Create unique filename
            var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
            var uploadPath = Path.Combine(_environment.WebRootPath, "uploads", folder);


            // Ensure directory exists
            Directory.CreateDirectory(uploadPath);


            var filePath = Path.Combine(uploadPath, fileName);


            try
            {
                // Save original file
                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }


                // Return relative path for database storage
                return $"/uploads/{folder}/{fileName}";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error uploading image: {FileName}", fileName);
                throw;
            }
        }


        public async Task<bool> DeleteImageAsync(string imagePath)
        {
            if (string.IsNullOrEmpty(imagePath))
                return false;


            try
            {
                var fullPath = Path.Combine(_environment.WebRootPath, imagePath.TrimStart('/'));


                if (File.Exists(fullPath))
                {
                    File.Delete(fullPath);
                    return true;
                }


                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting image: {ImagePath}", imagePath);
                return false;
            }
        }
       
        public bool IsValidImage(IFormFile file)
        {
            if (file == null || file.Length == 0)
                return false;


            if (file.Length > _maxFileSize)
                return false;


            var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
            if (!_allowedExtensions.Contains(extension))
                return false;


            // Check file signature (magic numbers)
            try
            {
                using var stream = file.OpenReadStream();
                using var image = Image.Load(stream);
                return true;
            }
            catch
            {
                return false;
            }
        }


        public async Task<string> ResizeImageAsync(string imagePath, int width, int height)
        {
            if (string.IsNullOrEmpty(imagePath))
                throw new ArgumentException("Image path is required");


            var fullPath = Path.Combine(_environment.WebRootPath, imagePath.TrimStart('/'));


            if (!File.Exists(fullPath))
                throw new FileNotFoundException("Image file not found");


            var fileName = Path.GetFileNameWithoutExtension(fullPath);
            var extension = Path.GetExtension(fullPath);
            var directory = Path.GetDirectoryName(fullPath);
            var resizedFileName = $"{fileName}_{width}x{height}{extension}";
            var resizedPath = Path.Combine(directory, resizedFileName);


            try
            {
                using var image = await Image.LoadAsync(fullPath);
                image.Mutate(x => x.Resize(width, height));
                await image.SaveAsync(resizedPath);


                // Return relative path
                var relativePath = Path.GetRelativePath(_environment.WebRootPath, resizedPath);
                return "/" + relativePath.Replace("\\", "/");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error resizing image: {ImagePath}", imagePath);
                throw;
            }
        }
    }


Register the service in the Program.cs

builder.Services.AddScoped<IImageService, ImageService>();


Inject it in your controller

public class PostsController : Controller
{
  private readonly IImageService _imageService;
   public PostsController(IImageService imageService)
   {

    _imageService = imageService;


    //You can use it like this in your action
        string? featuredImageUrl = null;
if (model.FeaturedImage != null)
{
    if (!_imageService.IsValidImage(model.FeaturedImage))
    {
        ModelState.AddModelError("FeaturedImage", "Please upload a valid image file (JPG, PNG, GIF, WebP) under 5MB.");
        await LoadViewBagData();
        return View(model);
    }

    featuredImageUrl = await _imageService.UploadImageAsync(model.FeaturedImage, "posts");
}
 
   }
}