using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using Azure; using Azure.Storage.Files.Shares; using gehGassi.Core.Interfaces; namespace gehGassi.External.Services { /// /// Service der die Verwaltung von Dateien als share ermöglicht. /// Alle Ordner und Dateinamen sind relativ anzugeben. /// z.B. test/Ordner1/order2 /// z.B. test/Ordner1/test.png /// public class AzureStorageFileShareService : IFileShareService { private readonly string _connectionString; /// /// Erstellt eine Instanz /// /// Connectionstring für Azure-Storage public AzureStorageFileShareService(string connectionString) { _connectionString = connectionString; } /// /// Auflisten der Ordner in einem Ordner /// /// Name des Shares /// Ordner /// Liste der Ordner im Share public List ListFolders(string shareName, string folder) { var list = new List(); var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var directory = rootDirectoryClient.GetSubdirectoryClient(folder); var itemsFound = directory.GetFilesAndDirectories(); foreach (var listFileItem in itemsFound) { if (listFileItem.IsDirectory) { var innerDirectoryClient = directory.GetSubdirectoryClient(listFileItem.Name); var innerDirItems = innerDirectoryClient.GetFilesAndDirectories(); var hasSubfolders = innerDirItems.Count(c => c.IsDirectory) > 0; var properties = innerDirectoryClient.GetProperties(); list.Add(new FolderResult() { Name = listFileItem.Name, LastModified = properties.Value.LastModified.DateTime, Created = properties.Value.SmbProperties.FileCreatedOn.Value.UtcDateTime, HasSubfolders = hasSubfolders }); } } return list; } /// /// Gibt Informationen über einen Ordner zurück /// /// Name des Shares /// Ordner /// Ordner oder null public FolderResult GetFolderInfo(string shareName, string folder) { FolderResult result = null; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var directory = rootDirectoryClient.GetSubdirectoryClient(folder); if (directory.Exists()) { var innerDirItems = directory.GetFilesAndDirectories(); var hasSubfolders = innerDirItems.Count(c => c.IsDirectory) > 0; var properties = directory.GetProperties(); result = new FolderResult() { Name = directory.Name, LastModified = properties.Value.LastModified.DateTime, Created = properties.Value.SmbProperties.FileCreatedOn.Value.UtcDateTime, HasSubfolders = hasSubfolders }; } return result; } /// /// Auflisten der Dateien in einem Ordner /// /// Name des Shares /// Ordner /// Liste der Dateien im Ordner public List ListFiles(string shareName, string folder) { var list = new List(); var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var directory = rootDirectoryClient.GetSubdirectoryClient(folder); if (directory.Exists()) { var itemsFound = directory.GetFilesAndDirectories(); foreach (var listFileItem in itemsFound) { if (!listFileItem.IsDirectory) { var fileClient = directory.GetFileClient(listFileItem.Name); var properties = fileClient.GetProperties(); list.Add(new FileResult() { Name = listFileItem.Name, LastModified = properties.Value.LastModified.DateTime, Created = properties.Value.SmbProperties.FileCreatedOn.Value.UtcDateTime, Size = properties.Value.ContentLength }); } } } return list; } /// /// Gibt Informationen über eine Datei zurück /// /// Name des Shares /// Dateiname relativ /// FileInfo oder null public FileResult GetFileInfo(string shareName, string fileName) { FileResult result = null; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileClient = rootDirectoryClient.GetFileClient(fileName); if (fileClient.Exists()) { var properties = fileClient.GetProperties(); result = new FileResult() { Name = fileClient.Name, LastModified = properties.Value.LastModified.DateTime, Created = properties.Value.SmbProperties.FileCreatedOn.Value.UtcDateTime, Size = properties.Value.ContentLength }; } return result; } /// /// Auflisten der Dateien und Ordner in einem Ordner /// /// Name des Shares /// Ordner /// Liste Dateien und Liste Ordner public (List, List) ListFilesAndFolders(string shareName, string folder) { var folders = new List(); var files = new List(); var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var directory = rootDirectoryClient.GetSubdirectoryClient(folder); var itemsFound = directory.GetFilesAndDirectories(); foreach (var listFileItem in itemsFound) { if (listFileItem.IsDirectory) { var innerDirectoryClient = directory.GetSubdirectoryClient(listFileItem.Name); var innerDirItems = innerDirectoryClient.GetFilesAndDirectories(); var hasSubfolders = innerDirItems.Count(c => c.IsDirectory) > 0; var properties = innerDirectoryClient.GetProperties(); folders.Add(new FolderResult() { Name = listFileItem.Name, LastModified = properties.Value.LastModified.DateTime, Created = properties.Value.SmbProperties.FileCreatedOn.Value.UtcDateTime, HasSubfolders = hasSubfolders }); } else { var fileClient = directory.GetFileClient(listFileItem.Name); var properties = fileClient.GetProperties(); files.Add(new FileResult() { Name = listFileItem.Name, LastModified = properties.Value.LastModified.DateTime, Created = properties.Value.SmbProperties.FileCreatedOn.Value.UtcDateTime, Size = properties.Value.ContentLength }); } } return (files, folders); } /// /// Anlegen eines Ordners. /// /// Name des Shares /// Neuer Ordner /// true wenn erfolgreich, false sonst public bool CreateFolder(string shareName, string newfolderName) { var success = false; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var pathChain = newfolderName.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (pathChain.Length == 1) { var folderClient = rootDirectoryClient.GetSubdirectoryClient(newfolderName); try { var response = folderClient.CreateIfNotExists(); success = true; } catch { success = false; } } else { try { foreach (var path in pathChain) { rootDirectoryClient = rootDirectoryClient.GetSubdirectoryClient(path); rootDirectoryClient.CreateIfNotExists(); success = true; } } catch { success = false; } } return success; } /// /// Speichern einer Datei /// /// Name des Shares /// Dateiname mit Ordnern relativ /// Datei /// true wenn überschrieben werden soll, false sonst /// true wenn erfolgreich, false sonst public bool Store(string shareName, string fileName, byte[] file, bool overwrite = false) { var success = false; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileClient = rootDirectoryClient.GetFileClient(fileName); var exists = fileClient.Exists(); if (!exists || overwrite) { try { if (exists && overwrite) fileClient.DeleteIfExists(); using (var stream = new MemoryStream(file)) { fileClient.Create(stream.Length); fileClient.Upload(stream); } success = true; } catch { success = false; } } return success; } /// /// Holt eine Datei /// /// Name des Shares /// Dateiname mit Ordnern relativ /// Datei oder null, wenn nicht gefunden public byte[] Get(string shareName, string fileName) { byte[] file = null; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileClient = rootDirectoryClient.GetFileClient(fileName); if (fileClient.Exists()) { var download = fileClient.Download(); using MemoryStream ms = new MemoryStream(); download.Value.Content.CopyTo(ms); file = ms.ToArray(); } return file; } /// /// Holt eine Datei als Stream /// /// Name des Shares /// Dateiname mit Ordnern relativ /// Stream oder null, wenn nicht gefunden public Stream GetStream(string shareName, string fileName) { var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileClient = rootDirectoryClient.GetFileClient(fileName); if (fileClient.Exists()) { var download = fileClient.Download(); if (download != null) { return download.Value.Content; } } return null; } /// /// Holt eine Datei als Stream /// /// Name des Shares /// Dateiname mit Ordnern relativ /// Wo soll gestartet werden /// Ende /// Stream oder null, wenn nicht gefunden public Stream GetStream(string shareName, string fileName, long start, long end) { var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileClient = rootDirectoryClient.GetFileClient(fileName); if (fileClient.Exists()) { var length = (end - start) + 1; var download = fileClient.Download(new HttpRange(start, length), false, CancellationToken.None); if (download != null) { return download.Value.Content; } } return null; } /// /// Umbenennen einer Datei /// /// Name des Shares /// Aktueller Dateiname /// Neuer Dateiname /// Soll eine Kopie gemacht werden? Wenn nicht wird die Quelldatei gelöscht /// true wenn erfolgreich, false sonst public bool RenameFile(string shareName, string fileName, string newFileName, bool copy) { var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileToRenameClient = rootDirectoryClient.GetFileClient(fileName); if (fileToRenameClient.Exists()) { byte[] file; var download = fileToRenameClient.Download(); using (var ms = new MemoryStream()) { download.Value.Content.CopyTo(ms); file = ms.ToArray(); } var fileToUpload = rootDirectoryClient.GetFileClient(newFileName); using (var stream = new MemoryStream(file)) { fileToUpload.Create(stream.Length); fileToUpload.Upload(stream); } if (!copy) DeleteFile(shareName, fileName); return true; } return false; } /// /// Umbenennen eines Ordners /// /// Name des Shares /// Aktueller Ordnername /// Neuer Ordnername /// Soll eine Kopie gemacht werden? Wenn nicht wird der QuellOrdner gelöscht /// true wenn erfolgreich, false sonst public bool RenameFolder(string shareName, string folder, string newFolder, bool copy) { var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var source = rootDirectoryClient.GetSubdirectoryClient(folder); var target = rootDirectoryClient.GetSubdirectoryClient(newFolder); target.CreateIfNotExists(); CopyAllItemsInFolder(source, target); if (!copy) DeleteFolder(shareName, folder); return true; } /// /// Umbenennen eines Ordners - Ohne TransferManager /// /// Name des Shares /// Aktueller Ordnername /// Neuer Ordnername /// Soll eine Kopie gemacht werden? Wenn nicht wird der QuellOrdner gelöscht /// true wenn erfolgreich, false sonst public bool RenameFolderEx(string shareName, string folder, string newFolder, bool copy) { var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var source = rootDirectoryClient.GetSubdirectoryClient(folder); var target = rootDirectoryClient.GetSubdirectoryClient(newFolder); target.CreateIfNotExists(); CopyAllItemsInFolder(source, target); if (!copy) DeleteFolder(shareName, folder); return true; } /// /// Löschen einer Datei /// /// Name des Shares /// Dateiname mit Ordnern relativ /// true wenn erfolgreich, false sonst public bool DeleteFile(string shareName, string fileName) { var success = false; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var fileClient = rootDirectoryClient.GetFileClient(fileName); if (fileClient.Exists()) { try { fileClient.Delete(); success = true; } catch { success = false; } } return success; } /// /// Löschen eines Ordners /// /// Name des Shares /// Ordner /// true wenn erfolgreich, false sonst public bool DeleteFolder(string shareName, string folder) { var success = false; var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var folderClient = rootDirectoryClient.GetSubdirectoryClient(folder); if (folderClient.Exists()) { try { DeleteAllItemsInFolder(folderClient); success = true; } catch { success = false; } } return success; } /// /// Löschen eines Shares /// /// Name des Shares /// true wenn erfolgreich, false sonst public bool DeleteShare(string shareName) { var success = false; var shareClient = new ShareClient(_connectionString, shareName); success = shareClient.DeleteIfExists(); return success; } /// /// Gibt die größe des Ordners (Dateien) als byte zurück /// /// Name des Shares /// Ordner /// Liste der Ordner im Share public long GetFolderSize(string shareName, string folder) { var shareClient = new ShareClient(_connectionString, shareName); shareClient.CreateIfNotExists(); var rootDirectoryClient = shareClient.GetRootDirectoryClient(); var directory = rootDirectoryClient.GetSubdirectoryClient(folder); long size = 0; var itemsFound = directory.GetFilesAndDirectories(); foreach (var listFileItem in itemsFound) { if (listFileItem.IsDirectory) { var innerDirectoryClient = directory.GetSubdirectoryClient(listFileItem.Name); InternalGetFolderSize(innerDirectoryClient, ref size); } else { var fileClient = directory.GetFileClient(listFileItem.Name); var properties = fileClient.GetProperties(); size += properties.Value.ContentLength; } } return size; } /// /// Rekursives Löschen eines Ordners /// /// Ordner-Referenz private void DeleteAllItemsInFolder(ShareDirectoryClient folderReference) { var allFilesAndFolders = folderReference.GetFilesAndDirectories(); foreach (var item in allFilesAndFolders) { if (item.IsDirectory) { var folder = folderReference.GetSubdirectoryClient(item.Name); DeleteAllItemsInFolder(folder); } else { var fileClient = folderReference.GetFileClient(item.Name); fileClient.DeleteIfExists(); } } folderReference.DeleteIfExists(); } /// /// Rekursives Kopieren eines Ordners /// /// Quelle /// Ziel private void CopyAllItemsInFolder(ShareDirectoryClient source, ShareDirectoryClient target) { var allFilesAndFolders = source.GetFilesAndDirectories(); foreach (var item in allFilesAndFolders) { if (item.IsDirectory) { var copyDir = target.GetSubdirectoryClient(item.Name); copyDir.CreateIfNotExists(); var sourceDir = source.GetSubdirectoryClient(item.Name); CopyAllItemsInFolder(sourceDir, copyDir); } else { var fileClient = source.GetFileClient(item.Name); var properties = fileClient.GetProperties(); var copyFile = target.GetFileClient(item.Name); copyFile.StartCopy(fileClient.Uri, properties.Value.Metadata, CancellationToken.None); } } } /// /// Hilfsmethode - rukrsiv Ordnergrößen anhand der Dateien berechnen /// /// ShareDirectoryClient /// Größe in bytes private void InternalGetFolderSize(ShareDirectoryClient client, ref long size) { var itemsFound = client.GetFilesAndDirectories(); foreach (var listFileItem in itemsFound) { if (listFileItem.IsDirectory) { var innerDirectoryClient = client.GetSubdirectoryClient(listFileItem.Name); InternalGetFolderSize(innerDirectoryClient, ref size); } else { var fileClient = client.GetFileClient(listFileItem.Name); var properties = fileClient.GetProperties(); size += properties.Value.ContentLength; } } } } }