kreta/Kreta.Core/FileService/FileService.cs
2024-03-13 00:33:46 +01:00

270 lines
9.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using Kreta.Core.FileService.Configuration;
namespace Kreta.Core.FileService
{
public class FileService : IFileService
{
private readonly IFileServiceConfiguration FileServiceConfiguration;
public FileService(IFileServiceConfiguration fileServiceConfiguration)
{
FileServiceConfiguration = fileServiceConfiguration ?? throw new ArgumentNullException(nameof(fileServiceConfiguration));
}
//konfigból jobb lenne
private readonly Dictionary<string, string> _allowedFileTypes =
new Dictionary<string, string>() {
{ ".txt", "text/plain" },
{ ".pdf", "application/pdf" },
{ ".png", "image/png" },
{ ".bmp", "image/bmp" },
{ ".jpg", "image/jpeg" },
{ ".jpeg", "image/jpeg" },
{ ".xls", "application/vnd.ms-excel" },
{ ".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
{ ".doc", "application/msword" },
{ ".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
{ ".xml", "text/xml" },
{ ".roz", "application/roz" },
{".rar", "application/octet-stream"},
{".zip", "application/x-zip-compressed"}
};
private Storage GetStorage(string storageName)
{
if (string.IsNullOrWhiteSpace(storageName))
{
throw new ArgumentException(nameof(storageName));
}
Storage storage = null;
foreach (Storage storageElement in FileServiceConfiguration.Storages)
{
if (storageElement.Key.Equals(storageName, StringComparison.OrdinalIgnoreCase))
{
storage = storageElement;
break;
}
}
if (storage == null)
{
throw new Exception("Nem létező storage name van megadva!");
}
return storage;
}
public string WriteToFile(string base64EncodedContent, string storageName)
{
Storage storage = GetStorage(storageName);
string newFileName = Guid.NewGuid().ToString();
string directoryPath = System.IO.Path.Combine(GetFileSharePath(storage), System.IO.Path.Combine(newFileName.Split('-')[0].Substring(0, 4).Select(x => x.ToString()).ToArray()));
try
{
Directory.CreateDirectory(directoryPath);
}
catch (Exception exception)
{
throw new Exception($"Hiba történt a mappa létrehozása során!", exception);
}
string filePath = System.IO.Path.Combine(directoryPath, newFileName);
string[] parts = base64EncodedContent.Split(new string[] { ";", ":", "," }, StringSplitOptions.None);
byte[] binaryFile = Convert.FromBase64String(parts[3]);
AttachmentValidation(binaryFile.Length, storage.MaxFileSizeInBytes, _allowedFileTypes.FirstOrDefault(x => x.Value == parts[1]).Key);
try
{
File.WriteAllBytes(filePath, binaryFile);
}
catch (Exception exception)
{
throw new Exception($"Hiba történt a fájl írása közben: {exception.Message}", exception);
}
return filePath;
}
public byte[] ReadFromFile(string filePath)
{
try
{
return File.ReadAllBytes(filePath);
}
catch (Exception exception)
{
throw new Exception($"Hiba történt a fájl olvasása közben: {exception.Message}", exception);
}
}
public string ReadImage(string filePath, string fileExtension)
{
byte[] imageContent = ReadFromFile(filePath);
if (imageContent != null)
{
return $"data:image/{fileExtension};base64,{Convert.ToBase64String(imageContent)}";
}
return null;
}
public string ReadAndResizeImage(string filePath, int width, int height)
{
byte[] imageContent = ReadFromFile(filePath);
if (imageContent != null)
{
Image image = CreateImage(imageContent);
return $"data:image/jpeg;base64,{Convert.ToBase64String(ResizeImage(image, width, height))}";
}
return null;
}
private Image CreateImage(byte[] pictureByteArray)
{
using (var memoryStream = new MemoryStream(pictureByteArray, 0, pictureByteArray.Length))
{
return Image.FromStream(memoryStream, true, true);
}
}
private byte[] ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
using (var destImage = new Bitmap(width, height))
{
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
using (var memoryStream = new MemoryStream())
{
destImage.Save(memoryStream, ImageFormat.Jpeg);
return memoryStream.ToArray();
}
}
}
private void AttachmentValidation(long contentLength, int maxFileSizeInBytes, string contentType)
{
if (contentType == null)
{
throw new Exception("Nem tölthető fel a fájl, mert nincs kiterjesztése");
}
if (!_allowedFileTypes.ContainsKey(contentType))
{
throw new Exception("Nem megengedett a fájl formátuma!");
}
if (contentLength > maxFileSizeInBytes)
{
throw new Exception("Nem tölthető fel a fájl, mert túl nagy a mérete");
}
}
private string GetFileSharePath(Storage storageElement)
{
string root = string.Empty;
foreach (Configuration.Path path in storageElement.Paths)
{
root = path.Value;
if (!HasEnoughFreeSpaceOnDisk(storageElement.MinimumRequiredFreeSpaceInBytes, root))
{
throw new Exception("Nincs elég hely a tárolón!");
}
break;
}
if (string.IsNullOrWhiteSpace(root))
{
throw new Exception("A megosztott meghajtó nincs megadva!");
}
return root;
}
private bool HasEnoughFreeSpaceOnDisk(int minimumRequiredFreeSpaceInBytes, string path)
{
if (string.IsNullOrWhiteSpace(path))
{
throw new ArgumentException(nameof(path));
}
//Nem működik a megosztott mappával
//TODO Imi: ellenőrizni, h létezik-e a megadott megosztott mappa
/*if (!Directory.Exists(path))
{
throw new ArgumentNullException("Nem létezik a file share!");
}*/
long freeSpaceInBytes = 0, dummy1 = 0, dummy2 = 0;
if (!GetDiskFreeSpaceEx(path, ref freeSpaceInBytes, ref dummy1, ref dummy2))
{
return false;
}
return freeSpaceInBytes > minimumRequiredFreeSpaceInBytes;
}
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage"), SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetDiskFreeSpaceEx
(
string lpszPath,
ref long lpFreeBytesAvailable,
ref long lpTotalNumberOfBytes,
ref long lpTotalNumberOfFreeBytes
);
public void DeleteFile(string filePath)
{
try
{
File.Delete(filePath);
}
catch (Exception ex)
{
throw new Exception("A fájl törlése sikertelen!", ex);
}
}
}
}