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 _allowedFileTypes = new Dictionary() { { ".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); } } } }