Add FolderWatcherService - PDF-Druck per Ordnerüberwachung
This commit is contained in:
parent
6720adfd96
commit
92e2767f76
4 changed files with 169 additions and 3 deletions
|
|
@ -21,6 +21,9 @@ public class MailPrintOptions
|
|||
public List<string> BlockedSenders { get; set; } = new();
|
||||
|
||||
public WebApiOptions WebApi { get; set; } = new();
|
||||
|
||||
/// <summary>Ordner-Überwachung: PDFs in diesen Ordnern werden automatisch gedruckt.</summary>
|
||||
public List<FolderWatcher> FolderWatchers { get; set; } = new();
|
||||
}
|
||||
|
||||
public class PrinterProfile
|
||||
|
|
@ -54,3 +57,15 @@ public class WebApiOptions
|
|||
public bool BindAllInterfaces { get; set; } = false;
|
||||
public string ApiKey { get; set; } = "";
|
||||
}
|
||||
|
||||
public class FolderWatcher
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
/// <summary>Zu überwachender Ordner (vollständiger Pfad)</summary>
|
||||
public string Path { get; set; } = "";
|
||||
/// <summary>Auch Unterordner überwachen</summary>
|
||||
public bool IncludeSubfolders { get; set; } = false;
|
||||
/// <summary>Datei nach erfolgreichem Druck löschen</summary>
|
||||
public bool DeleteAfterPrint { get; set; } = true;
|
||||
public string PrinterProfileName { get; set; } = "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,29 +8,38 @@ public class MailPrintWorker : BackgroundService
|
|||
private readonly ILogger<MailPrintWorker> _logger;
|
||||
private readonly MailFetchService _mailService;
|
||||
private readonly PrintService _printService;
|
||||
private readonly FolderWatcherService _folderService;
|
||||
private readonly MailPrintOptions _options;
|
||||
|
||||
public MailPrintWorker(ILogger<MailPrintWorker> logger, MailFetchService mailService,
|
||||
PrintService printService, IOptions<MailPrintOptions> options)
|
||||
public MailPrintWorker(
|
||||
ILogger<MailPrintWorker> logger,
|
||||
MailFetchService mailService,
|
||||
PrintService printService,
|
||||
FolderWatcherService folderService,
|
||||
IOptions<MailPrintOptions> options)
|
||||
{
|
||||
_logger = logger;
|
||||
_mailService = mailService;
|
||||
_printService = printService;
|
||||
_folderService = folderService;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken ct)
|
||||
{
|
||||
// Ordner-Überwachung starten (event-basiert, läuft dauerhaft)
|
||||
_folderService.Start();
|
||||
|
||||
if (_options.Accounts.Count == 0)
|
||||
{
|
||||
_logger.LogWarning("Keine Postfächer konfiguriert – Mail-Polling deaktiviert.");
|
||||
await Task.Delay(Timeout.Infinite, ct).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("{Count} Postfach/Postfächer konfiguriert, Intervall: {Interval}s",
|
||||
_options.Accounts.Count, _options.PollIntervalSeconds);
|
||||
|
||||
// Pro Account einen eigenen Poll-Loop starten
|
||||
var tasks = _options.Accounts.Select(account => PollAccountAsync(account, ct));
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ try
|
|||
builder.Services.Configure<MailPrintOptions>(builder.Configuration.GetSection("MailPrint"));
|
||||
builder.Services.AddSingleton<PrintService>();
|
||||
builder.Services.AddSingleton<MailFetchService>();
|
||||
builder.Services.AddSingleton<FolderWatcherService>();
|
||||
builder.Services.AddHostedService<MailPrintWorker>();
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
|
|
|
|||
141
MailPrint/Services/FolderWatcherService.cs
Normal file
141
MailPrint/Services/FolderWatcherService.cs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace MailPrint.Services;
|
||||
|
||||
public class FolderWatcherService : IDisposable
|
||||
{
|
||||
private readonly ILogger<FolderWatcherService> _logger;
|
||||
private readonly PrintService _printService;
|
||||
private readonly MailPrintOptions _options;
|
||||
private readonly List<FileSystemWatcher> _watchers = new();
|
||||
|
||||
public FolderWatcherService(
|
||||
ILogger<FolderWatcherService> logger,
|
||||
PrintService printService,
|
||||
IOptions<MailPrintOptions> options)
|
||||
{
|
||||
_logger = logger;
|
||||
_printService = printService;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_options.FolderWatchers.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("Keine Ordner-Überwachung konfiguriert.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var config in _options.FolderWatchers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(config.Path) || !Directory.Exists(config.Path))
|
||||
{
|
||||
_logger.LogWarning("[{Name}] Ordner nicht gefunden: {Path}", config.Name, config.Path);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Beim Start bereits vorhandene PDFs drucken
|
||||
PrintExistingFiles(config);
|
||||
|
||||
var watcher = new FileSystemWatcher(config.Path)
|
||||
{
|
||||
Filter = "*.pdf",
|
||||
IncludeSubdirectories = config.IncludeSubfolders,
|
||||
NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite,
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
|
||||
watcher.Created += (_, e) => OnFileDetected(e.FullPath, config);
|
||||
watcher.Renamed += (_, e) =>
|
||||
{
|
||||
if (e.Name?.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase) == true)
|
||||
OnFileDetected(e.FullPath, config);
|
||||
};
|
||||
|
||||
_watchers.Add(watcher);
|
||||
_logger.LogInformation("[{Name}] Überwache: {Path} (Unterordner: {Sub})",
|
||||
config.Name, config.Path, config.IncludeSubfolders);
|
||||
}
|
||||
}
|
||||
|
||||
private void PrintExistingFiles(FolderWatcher config)
|
||||
{
|
||||
var files = Directory.GetFiles(config.Path, "*.pdf",
|
||||
config.IncludeSubfolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
|
||||
|
||||
if (files.Length == 0) return;
|
||||
|
||||
_logger.LogInformation("[{Name}] {Count} vorhandene PDF(s) gefunden – werden gedruckt.", config.Name, files.Length);
|
||||
foreach (var file in files)
|
||||
OnFileDetected(file, config);
|
||||
}
|
||||
|
||||
private void OnFileDetected(string filePath, FolderWatcher config)
|
||||
{
|
||||
// Kurz warten bis Datei vollständig geschrieben ist
|
||||
if (!WaitForFile(filePath))
|
||||
{
|
||||
_logger.LogWarning("[{Name}] Datei nicht lesbar (gesperrt?): {File}", config.Name, filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("[{Name}] Neue Datei: {File}", config.Name, filePath);
|
||||
|
||||
try
|
||||
{
|
||||
_printService.PrintPdf(new PrintJob
|
||||
{
|
||||
FilePath = filePath,
|
||||
MailSubject = Path.GetFileName(filePath),
|
||||
MailFrom = $"Ordner:{config.Name}",
|
||||
PrinterProfileName = config.PrinterProfileName
|
||||
});
|
||||
|
||||
if (config.DeleteAfterPrint)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(filePath);
|
||||
_logger.LogInformation("[{Name}] Gelöscht: {File}", config.Name, filePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "[{Name}] Löschen fehlgeschlagen: {File}", config.Name, filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "[{Name}] Druckfehler: {File}", config.Name, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool WaitForFile(string path, int timeoutMs = 5000)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
while (sw.ElapsedMilliseconds < timeoutMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
return true;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var w in _watchers)
|
||||
{
|
||||
w.EnableRaisingEvents = false;
|
||||
w.Dispose();
|
||||
}
|
||||
_watchers.Clear();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue