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;
}
}
}
}
}