gehgassi_backend/gehGassi.External/Services/AzureStorageFileShareService.cs

680 lines
25 KiB
C#

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
{
/// <summary>
/// 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
/// </summary>
public class AzureStorageFileShareService : IFileShareService
{
private readonly string _connectionString;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="connectionString">Connectionstring für Azure-Storage</param>
public AzureStorageFileShareService(string connectionString)
{
_connectionString = connectionString;
}
/// <summary>
/// Auflisten der Ordner in einem Ordner
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Ordner</param>
/// <returns>Liste der Ordner im Share</returns>
public List<FolderResult> ListFolders(string shareName, string folder)
{
var list = new List<FolderResult>();
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;
}
/// <summary>
/// Gibt Informationen über einen Ordner zurück
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Ordner</param>
/// <returns>Ordner oder null</returns>
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;
}
/// <summary>
/// Auflisten der Dateien in einem Ordner
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Ordner</param>
/// <returns>Liste der Dateien im Ordner</returns>
public List<FileResult> ListFiles(string shareName, string folder)
{
var list = new List<FileResult>();
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;
}
/// <summary>
/// Gibt Informationen über eine Datei zurück
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Dateiname relativ</param>
/// <returns>FileInfo oder null</returns>
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;
}
/// <summary>
/// Auflisten der Dateien und Ordner in einem Ordner
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Ordner</param>
/// <returns>Liste Dateien und Liste Ordner</returns>
public (List<FileResult>, List<FolderResult>) ListFilesAndFolders(string shareName, string folder)
{
var folders = new List<FolderResult>();
var files = new List<FileResult>();
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);
}
/// <summary>
/// Anlegen eines Ordners.
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="newfolderName">Neuer Ordner</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Speichern einer Datei
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Dateiname mit Ordnern relativ</param>
/// <param name="file">Datei</param>
/// <param name="overwrite">true wenn überschrieben werden soll, false sonst</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Holt eine Datei
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Dateiname mit Ordnern relativ</param>
/// <returns>Datei oder null, wenn nicht gefunden</returns>
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;
}
/// <summary>
/// Holt eine Datei als Stream
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Dateiname mit Ordnern relativ</param>
/// <returns>Stream oder null, wenn nicht gefunden</returns>
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;
}
/// <summary>
/// Holt eine Datei als Stream
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Dateiname mit Ordnern relativ</param>
/// <param name="start">Wo soll gestartet werden</param>
/// <param name="end">Ende</param>
/// <returns>Stream oder null, wenn nicht gefunden</returns>
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;
}
/// <summary>
/// Umbenennen einer Datei
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Aktueller Dateiname</param>
/// <param name="newFileName">Neuer Dateiname</param>
/// <param name="copy">Soll eine Kopie gemacht werden? Wenn nicht wird die Quelldatei gelöscht</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Umbenennen eines Ordners
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Aktueller Ordnername</param>
/// <param name="newFolder">Neuer Ordnername</param>
/// <param name="copy">Soll eine Kopie gemacht werden? Wenn nicht wird der QuellOrdner gelöscht</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Umbenennen eines Ordners - Ohne TransferManager
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Aktueller Ordnername</param>
/// <param name="newFolder">Neuer Ordnername</param>
/// <param name="copy">Soll eine Kopie gemacht werden? Wenn nicht wird der QuellOrdner gelöscht</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Löschen einer Datei
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="fileName">Dateiname mit Ordnern relativ</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Löschen eines Ordners
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Ordner</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
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;
}
/// <summary>
/// Löschen eines Shares
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public bool DeleteShare(string shareName)
{
var success = false;
var shareClient = new ShareClient(_connectionString, shareName);
success = shareClient.DeleteIfExists();
return success;
}
/// <summary>
/// Gibt die größe des Ordners (Dateien) als byte zurück
/// </summary>
/// <param name="shareName">Name des Shares</param>
/// <param name="folder">Ordner</param>
/// <returns>Liste der Ordner im Share</returns>
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;
}
/// <summary>
/// Rekursives Löschen eines Ordners
/// </summary>
/// <param name="folderReference">Ordner-Referenz</param>
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();
}
/// <summary>
/// Rekursives Kopieren eines Ordners
/// </summary>
/// <param name="source">Quelle</param>
/// <param name="target">Ziel</param>
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);
}
}
}
/// <summary>
/// Hilfsmethode - rukrsiv Ordnergrößen anhand der Dateien berechnen
/// </summary>
/// <param name="client">ShareDirectoryClient</param>
/// <param name="size">Größe in bytes</param>
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;
}
}
}
}
}