PlotDirector/PlotLine/Services/HardDeleteFileCleanupService.cs

93 lines
3.6 KiB
C#

namespace PlotLine.Services;
public interface IHardDeleteFileCleanupService
{
HardDeleteFileCleanupResult DeleteFiles(string operationName, int ownerId, IReadOnlyList<string> storagePaths);
}
public sealed record HardDeleteFileCleanupResult(int Deleted, int Missing, int Failed);
public sealed class HardDeleteFileCleanupService(
IUploadStorageService uploadStorage,
ILogger<HardDeleteFileCleanupService> logger) : IHardDeleteFileCleanupService
{
public HardDeleteFileCleanupResult DeleteFiles(string operationName, int ownerId, IReadOnlyList<string> storagePaths)
{
var deleted = 0;
var missing = 0;
var failed = 0;
var deletedDirectories = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var storagePath in storagePaths)
{
var absolutePath = uploadStorage.TryResolvePublicPath(storagePath);
if (absolutePath is null)
{
logger.LogWarning("Hard delete skipped a non-local upload path during {OperationName} for owner {OwnerID}.", operationName, ownerId);
continue;
}
if (!File.Exists(absolutePath))
{
missing++;
logger.LogInformation("Hard delete file cleanup found a missing file during {OperationName} for owner {OwnerID}.", operationName, ownerId);
continue;
}
try
{
File.Delete(absolutePath);
deleted++;
logger.LogInformation("Hard delete removed an uploaded file during {OperationName} for owner {OwnerID}.", operationName, ownerId);
var directory = Path.GetDirectoryName(absolutePath);
if (!string.IsNullOrWhiteSpace(directory))
{
deletedDirectories.Add(directory);
}
}
catch (Exception ex)
{
failed++;
logger.LogWarning(ex, "Hard delete could not remove an uploaded file during {OperationName} for owner {OwnerID}.", operationName, ownerId);
}
}
foreach (var directory in deletedDirectories.OrderByDescending(x => x.Length))
{
TryDeleteEmptyUploadDirectory(operationName, ownerId, directory);
}
return new HardDeleteFileCleanupResult(deleted, missing, failed);
}
private void TryDeleteEmptyUploadDirectory(string operationName, int ownerId, string directory)
{
var uploadsRoot = Path.EndsInDirectorySeparator(uploadStorage.UploadsRootPath)
? uploadStorage.UploadsRootPath
: uploadStorage.UploadsRootPath + Path.DirectorySeparatorChar;
var comparison = OperatingSystem.IsWindows()
? StringComparison.OrdinalIgnoreCase
: StringComparison.Ordinal;
var fullDirectory = Path.GetFullPath(directory);
if (!fullDirectory.StartsWith(uploadsRoot, comparison)
|| string.Equals(fullDirectory, uploadStorage.UploadsRootPath, comparison))
{
return;
}
try
{
if (Directory.Exists(fullDirectory) && !Directory.EnumerateFileSystemEntries(fullDirectory).Any())
{
Directory.Delete(fullDirectory);
logger.LogInformation("Hard delete removed an empty upload directory during {OperationName} for owner {OwnerID}.", operationName, ownerId);
}
}
catch (Exception ex)
{
logger.LogWarning(ex, "Hard delete could not remove an empty upload directory during {OperationName} for owner {OwnerID}.", operationName, ownerId);
}
}
}