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");
}
}
}
Comments (0)
Leave a Comment