Modern web uygulamalarında dosya yükleme, kullanıcıların görseller, belgeler veya tablolar gibi farklı dosya türlerini yüklemelerine olanak tanır. Bu blog yazısında, ASP.NET Core MVC uygulamasında dosya yükleme işlemi gerçekleştireceğiz. Ayrıca, görselleri yeniden boyutlandırma, dosya türü doğrulama ve dosya adlarının güvenli bir şekilde işlenmesi gibi konuları ele alacağız.
Gereksinimler
Kodumuza başlamadan önce, görsel işleme görevlerini kolayca gerçekleştirebilmek için SixLabors.ImageSharp paketini yüklememiz gerekecek. Bu kütüphane, ASP.NET Core ile entegre bir şekilde görselleri işlemek için mükemmel bir seçenektir.
Aşağıdaki komutu çalıştırarak ImageSharp paketini yükleyebilirsiniz:
dotnet add package SixLabors.ImageSharp --version 3.1.5
Bu komut, SixLabors.ImageSharp kütüphanesinin 3.1.5 sürümünü yükleyecektir. Bu sürüm, görselleri yeniden boyutlandırma ve işlemeye yönelik ihtiyaçlarımızı karşılayacaktır.
Kod İncelemesi
1. Dosya Yükleme için Controller Oluşturma
Aşağıdaki kodda, HomeController isminde bir controller oluşturduk. Bu controller, dosya yüklemeyi işler ve yüklenen dosyaların güvenliğini sağlamak için çeşitli doğrulamalar yapar. Controller, iki ana metot içeriyor:
Index(): Kullanıcılara dosya yükleyebilecekleri bir HTML formu sunar.UploadFile(): Dosya yükleme işlemini yönetir, dosya türünü ve boyutunu doğrular ve dosyayı sunucuya kaydeder.
using Microsoft.AspNetCore.Mvc;
namespace FileUpload.Controllers
{
public class HomeController : Controller
{
// GET: /Home/Index
[HttpGet]
[Route("/")]
public IActionResult Index()
{
// HTML formunu döndür
return Content(@"
<html>
<head><meta charset=""utf-8""></head>
<body>
<h2>Dosya Yükleyin</h2>
<form action=""/Home/UploadFile"" method=""post"" enctype=""multipart/form-data"">
<label for=""file"">Dosya Seçin:</label>
<input type=""file"" name=""file"" required />
<button type=""submit"">Yükle</button>
</form>
</body>
</html>", "text/html");
}
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
var isUploaded = await FileUploadHelper.UploadFileAsync(file, file.FileName, Path.Combine("wwwroot/uploads"));
if (Convert.ToBoolean(isUploaded["status"]))
{
return Ok(isUploaded);
}
else
{
return BadRequest("Dosya yükleme başarısız oldu. Lütfen dosya türünü ve boyutunu kontrol edip tekrar deneyin.");
}
}
}
}
2. Dosya Yükleme ve İşleme Yardımcı Sınıfı
Dosya yükleme ve işleme işlemlerini yöneten bir yardımcı sınıf (FileUploadHelper) oluşturduk. Bu sınıf, dosya adlarını güvenli hale getirir, dosya türlerini doğrular ve görsellerin boyutunu yeniden düzenler.
İşte FileUploadHelper sınıfının kodu:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System.Text.RegularExpressions;
public class FileUploadHelper
{
public static async Task<Dictionary<string, object>> UploadFileAsync(IFormFile file, string fileName, string uploadPath, bool deleteIfExists = false)
{
var result = new Dictionary<string, object>
{
{ "status", false },
{ "fileName", "" }
};
if (file == null || file.Length == 0)
{
return result; // Dosya boşsa veya yüklenmediyse false döner
}
// Türkçe karakterleri güvenli hale getirmek için dosya adını temizleyin
fileName = MakeFileNameSafe(fileName);
// Geçerli dosya türlerini kontrol et (Updated file types)
var allowedTypes = new[] {
"image/jpeg", "image/jpg", "image/png", "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", // Word formats
"application/vnd.ms-excel", "application/vnd.openxmlformats.officedocument.spreadsheetml.sheet", // Excel formats
"image/svg+xml", "application/vnd.oasis.opendocument.text", "application/vnd.oasis.opendocument.spreadsheet", // ODT, ODS, SVG
"image/webp"
};
if (!allowedTypes.Contains(file.ContentType))
{
return result; // Desteklenmeyen dosya türü
}
// Dosya boyutunu kontrol et (5 MB sınırı)
const long maxFileSize = 5 * 1024 * 1024;
if (file.Length > maxFileSize)
{
return result; // Dosya çok büyükse
}
try
{
var filePath = Path.Combine(uploadPath, fileName);
// Check if the file already exists
if (File.Exists(filePath))
{
if (deleteIfExists)
{
// If deleteIfExists is true, delete the existing file
File.Delete(filePath);
}
else
{
// If file exists and deleteIfExists is false, generate a unique name
fileName = GenerateUniqueFileName(uploadPath, fileName);
filePath = Path.Combine(uploadPath, fileName);
}
}
// If the file is an image, handle it separately
if (file.ContentType.StartsWith("image"))
{
using var image = await Image.LoadAsync(file.OpenReadStream());
// Resize the image to a maximum of 800x800 pixels
int maxWidth = 800;
int maxHeight = 800;
image.Mutate(x => x.Resize(new ResizeOptions
{
Mode = ResizeMode.Max,
Size = new Size(maxWidth, maxHeight)
}));
// Save the resized image to the specified file path
await image.SaveAsync(filePath);
}
else
{
// If the file is not an image, save it directly to the file system
using var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous);
await file.CopyToAsync(stream);
}
// If upload is successful, update the result dictionary
result["status"] = true;
result["fileName"] = fileName; // Set the uploaded file name
}
catch (Exception)
{
return result; // Hata varsa status false döner
}
return result;
}
private static string MakeFileNameSafe(string fileName)
{
// Güvenlik amacıyla geçersiz karakterleri temizlerken Türkçe karakterleri koruyun
fileName = Regex.Replace(fileName, @"[<>:""/\\|?*]", ""); // Yasaklı karakterleri kaldır
// Boşlukları ve diğer özel karakterleri "-" ile değiştirin, Türkçe karakterleri olduğu gibi bırakın
return Regex.Replace(fileName, @"\s+", "-");
}
private static string GenerateUniqueFileName(string uploadPath, string fileName)
{
var fileExtension = Path.GetExtension(fileName);
var baseFileName = Path.GetFileNameWithoutExtension(fileName);
// Create a unique name by appending a timestamp to the original file name
var uniqueFileName = $"{baseFileName}_{DateTime.UtcNow.Ticks}{fileExtension}";
var uniqueFilePath = Path.Combine(uploadPath, uniqueFileName);
// Ensure that the generated unique name doesn't collide with an existing file
while (File.Exists(uniqueFilePath))
{
uniqueFileName = $"{baseFileName}_{DateTime.UtcNow.Ticks}{fileExtension}";
uniqueFilePath = Path.Combine(uploadPath, uniqueFileName);
}
return uniqueFileName;
}
}
TAM KOD
HomeController.cs
using Microsoft.AspNetCore.Mvc;
namespace FileUpload.Controllers
{
public class HomeController : Controller
{
// GET: /Home/Index
[HttpGet]
[Route("/")]
public IActionResult Index()
{
// HTML formunu döndür
return Content(@"
<html>
<head><meta charset=""utf-8""></head>
<body>
<h2>Upload a File</h2>
<form action=""/Home/UploadFile"" method=""post"" enctype=""multipart/form-data"">
<label for=""file"">Choose file:</label>
<input type=""file"" name=""file"" required />
<button type=""submit"">Upload</button>
</form>
</body>
</html>", "text/html");
}
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
var isUploaded = await FileUploadHelper.UploadFileAsync(file, file.FileName, Path.Combine("wwwroot/uploads"));
if (Convert.ToBoolean(isUploaded["status"]))
{
return Ok(isUploaded);
}
else
{
return BadRequest("File upload failed. Please check file type, size, and try again.");
}
}
}
}
Models/FileUploads.cs
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System.Text.RegularExpressions;
public class FileUploadHelper
{
public static async Task<Dictionary<string, object>> UploadFileAsync(IFormFile file, string fileName, string uploadPath, bool deleteIfExists = false)
{
var result = new Dictionary<string, object>
{
{ "status", false },
{ "fileName", "" }
};
if (file == null || file.Length == 0)
{
return result; // Dosya boşsa veya yüklenmediyse false döner
}
// Türkçe karakterleri güvenli hale getirmek için dosya adını temizleyin
fileName = MakeFileNameSafe(fileName);
// Geçerli dosya türlerini kontrol et (Updated file types)
var allowedTypes = new[] {
"image/jpeg", "image/jpg", "image/png", "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", // Word formats
"application/vnd.ms-excel", "application/vnd.openxmlformats.officedocument.spreadsheetml.sheet", // Excel formats
"image/svg+xml", "application/vnd.oasis.opendocument.text", "application/vnd.oasis.opendocument.spreadsheet", // ODT, ODS, SVG
"image/webp"
};
if (!allowedTypes.Contains(file.ContentType))
{
return result; // Desteklenmeyen dosya türü
}
// Dosya boyutunu kontrol et (5 MB sınırı)
const long maxFileSize = 5 * 1024 * 1024;
if (file.Length > maxFileSize)
{
return result; // Dosya çok büyükse
}
try
{
var filePath = Path.Combine(uploadPath, fileName);
// Check if the file already exists
if (File.Exists(filePath))
{
if (deleteIfExists)
{
// If deleteIfExists is true, delete the existing file
File.Delete(filePath);
}
else
{
// If file exists and deleteIfExists is false, generate a unique name
fileName = GenerateUniqueFileName(uploadPath, fileName);
filePath = Path.Combine(uploadPath, fileName);
}
}
// If the file is an image, handle it separately
if (file.ContentType.StartsWith("image"))
{
using var image = await Image.LoadAsync(file.OpenReadStream());
// Resize the image to a maximum of 800x800 pixels
int maxWidth = 800;
int maxHeight = 800;
image.Mutate(x => x.Resize(new ResizeOptions
{
Mode = ResizeMode.Max,
Size = new Size(maxWidth, maxHeight)
}));
// Save the resized image to the specified file path
await image.SaveAsync(filePath);
}
else
{
// If the file is not an image, save it directly to the file system
using var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous);
await file.CopyToAsync(stream);
}
// If upload is successful, update the result dictionary
result["status"] = true;
result["fileName"] = fileName; // Set the uploaded file name
}
catch (Exception)
{
return result; // Hata varsa status false döner
}
return result;
}
private static string MakeFileNameSafe(string fileName)
{
// Güvenlik amacıyla geçersiz karakterleri temizlerken Türkçe karakterleri koruyun
fileName = Regex.Replace(fileName, @"[<>:""/\\|?*]", ""); // Yasaklı karakterleri kaldır
// Boşlukları ve diğer özel karakterleri "-" ile değiştirin, Türkçe karakterleri olduğu gibi bırakın
return Regex.Replace(fileName, @"\s+", "-");
}
private static string GenerateUniqueFileName(string uploadPath, string fileName)
{
var fileExtension = Path.GetExtension(fileName);
var baseFileName = Path.GetFileNameWithoutExtension(fileName);
// Create a unique name by appending a timestamp to the original file name
var uniqueFileName = $"{baseFileName}_{DateTime.UtcNow.Ticks}{fileExtension}";
var uniqueFilePath = Path.Combine(uploadPath, uniqueFileName);
// Ensure that the generated unique name doesn't collide with an existing file
while (File.Exists(uniqueFilePath))
{
uniqueFileName = $"{baseFileName}_{DateTime.UtcNow.Ticks}{fileExtension}";
uniqueFilePath = Path.Combine(uploadPath, uniqueFileName);
}
return uniqueFileName;
}
}
Sonuç
Bu basit uygulama sayesinde, ASP.NET Core MVC ile dosya yükleme işlemi gerçekleştirebilir, yüklenen dosyaları güvenli bir şekilde sunucuda depolayabilir ve görsellerin boyutunu istediğiniz şekilde yeniden boyutlandırabilirsiniz. Ayrıca, dosya türü ve boyutu doğrulaması ile sadece geçerli dosyaların yüklenmesini sağlarsınız.
Bu blogda kullanılan SixLabors.ImageSharp kütüphanesini yüklemek için:
dotnet add package SixLabors.ImageSharp --version 3.1.5
Komutunu kullanarak görsel işleme işlemlerini kolayca gerçekleştirebilirsiniz.
Umarım bu yazı, ASP.NET Core’da dosya yükleme ve güvenli dosya işleme konularında size yardımcı olmuştur!