Base Zooflow Filehandling
This commit is contained in:
346
Base/DocumentPathHandler.vb
Normal file
346
Base/DocumentPathHandler.vb
Normal file
@@ -0,0 +1,346 @@
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Logging
|
||||
''' <summary>
|
||||
''' Zentrale Klasse für Dokumentenpfad-Verwaltung mit optionalem Laufwerks-Mapping und Temp-Kopie
|
||||
''' </summary>
|
||||
Public Class DocumentPathHandler
|
||||
|
||||
Private ReadOnly _Logger As Logger
|
||||
Private ReadOnly _LogConfig As LogConfig
|
||||
Private _mappedDrive As String = ""
|
||||
Private _clsmapDrive As Map_Drive
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
_LogConfig = LogConfig
|
||||
_Logger = LogConfig.GetLogger()
|
||||
_clsmapDrive = New Map_Drive(LogConfig)
|
||||
End Sub
|
||||
|
||||
Private Function EnsureTempFolder(ByRef tempFolder As String, ByRef errorMessage As String) As Boolean
|
||||
Try
|
||||
_Logger.Debug($"📂 Überprüfe Temp-Ordner: [{tempFolder}]")
|
||||
If String.IsNullOrWhiteSpace(tempFolder) Then
|
||||
_Logger.Debug("⚠️ Temp-Ordner nicht konfiguriert, verwende TEMP_DOCUMENT_FOLDER aus AppSettings")
|
||||
tempFolder = TEMP_DOCUMENT_FOLDER
|
||||
End If
|
||||
|
||||
' Fallback, falls global nichts konfiguriert ist
|
||||
If String.IsNullOrWhiteSpace(tempFolder) Then
|
||||
tempFolder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Digital Data",
|
||||
"taskFLOW",
|
||||
"DocumentViewer",
|
||||
"Temp")
|
||||
_Logger.Info($"⚠️ TEMP_DOCUMENT_FOLDER war leer - verwende Fallback: [{tempFolder}]")
|
||||
TEMP_DOCUMENT_FOLDER = tempFolder
|
||||
End If
|
||||
|
||||
If Not Directory.Exists(tempFolder) Then
|
||||
Directory.CreateDirectory(tempFolder)
|
||||
_Logger.Info($"📁 Temp-Ordner erstellt: [{tempFolder}]")
|
||||
End If
|
||||
|
||||
If Not Directory.Exists(tempFolder) Then
|
||||
errorMessage = $"Temp-Ordner konnte nicht erstellt werden: [{tempFolder}]"
|
||||
Return False
|
||||
End If
|
||||
|
||||
Return True
|
||||
|
||||
Catch ex As Exception
|
||||
errorMessage = $"Fehler bei Temp-Ordner-Initialisierung: {ex.Message}"
|
||||
_Logger.Error($"❌ {errorMessage}")
|
||||
_Logger.Error(ex)
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
''' <summary>
|
||||
''' Verarbeitet einen Dokumentenpfad: Optional Mapping, dann Temp-Kopie
|
||||
''' </summary>
|
||||
''' <param name="sourcePath">Quell-Pfad der Datei (UNC oder lokal)</param>
|
||||
''' <param name="options">Optionen für die Verarbeitung</param>
|
||||
''' <returns>DocumentPathResult mit finalem Pfad und Mapping-Info</returns>
|
||||
Public Function ProcessDocumentPath(sourcePath As String, options As DocumentPathOptions) As DocumentPathResult
|
||||
Dim result As New DocumentPathResult With {
|
||||
.SourcePath = sourcePath,
|
||||
.FinalPath = sourcePath,
|
||||
.Success = False,
|
||||
.WasMapped = False,
|
||||
.WasCopiedToTemp = False
|
||||
}
|
||||
|
||||
Try
|
||||
' Validierung
|
||||
If String.IsNullOrEmpty(sourcePath) Then
|
||||
result.ErrorMessage = "Quell-Pfad ist leer"
|
||||
_Logger.Error("❌ ProcessDocumentPath: Quell-Pfad ist leer")
|
||||
Return result
|
||||
End If
|
||||
|
||||
Dim workingPath As String = sourcePath
|
||||
|
||||
' ========== SCHRITT 1: OPTIONALES LAUFWERKS-MAPPING ==========
|
||||
If options.EnableMapping AndAlso Not String.IsNullOrEmpty(options.WMSuffix) Then
|
||||
Dim mappingResult = TryMapNetworkDrive(sourcePath, options)
|
||||
If mappingResult.Success Then
|
||||
workingPath = mappingResult.MappedPath
|
||||
_mappedDrive = mappingResult.DriveLetter
|
||||
result.WasMapped = True
|
||||
result.MappedDrive = _mappedDrive
|
||||
_Logger.Info($"✓ Laufwerk gemappt: {_mappedDrive}")
|
||||
Else
|
||||
_Logger.Warn("⚠️ Laufwerks-Mapping fehlgeschlagen - verwende Original-UNC-Pfad")
|
||||
workingPath = sourcePath
|
||||
End If
|
||||
End If
|
||||
|
||||
' ========== SCHRITT 2: PRÜFEN OB DATEI EXISTIERT ==========
|
||||
If Not File.Exists(workingPath) Then
|
||||
result.ErrorMessage = $"Datei nicht gefunden: [{workingPath}]"
|
||||
_Logger.Error($"❌ {result.ErrorMessage}")
|
||||
|
||||
' Cleanup bei Fehler
|
||||
If result.WasMapped Then
|
||||
UnmapDrive()
|
||||
End If
|
||||
|
||||
Return result
|
||||
End If
|
||||
|
||||
' ========== SCHRITT 3: OPTIONALE TEMP-KOPIE ==========
|
||||
If options.CopyToTemp Then
|
||||
_Logger.Debug($"📂 Starte Temp-Kopie für: [{workingPath}]")
|
||||
Dim tempResult = CopyToTempFolder(workingPath, options.TempFolder)
|
||||
If tempResult.Success Then
|
||||
result.FinalPath = tempResult.TempPath
|
||||
result.WasCopiedToTemp = True
|
||||
result.TempPath = tempResult.TempPath
|
||||
_Logger.Info($"✓ Datei in Temp kopiert: [{Path.GetFileName(tempResult.TempPath)}]")
|
||||
|
||||
' Laufwerk unmappen nach erfolgreicher Kopie
|
||||
If result.WasMapped AndAlso options.UnmapAfterCopy Then
|
||||
UnmapDrive()
|
||||
result.WasMapped = False
|
||||
End If
|
||||
Else
|
||||
_Logger.Warn($"⚠️ Temp-Kopie fehlgeschlagen: {tempResult.ErrorMessage}")
|
||||
|
||||
' WICHTIG: Nicht den gemappten Pfad behalten, wenn danach ungemappt wird.
|
||||
' Fallback immer auf stabilen Originalpfad (UNC).
|
||||
result.FinalPath = sourcePath
|
||||
result.WasCopiedToTemp = False
|
||||
result.TempPath = String.Empty
|
||||
|
||||
If result.WasMapped Then
|
||||
UnmapDrive()
|
||||
result.WasMapped = False
|
||||
End If
|
||||
End If
|
||||
Else
|
||||
result.FinalPath = workingPath
|
||||
_Logger.Debug($"📄 Verwende Pfad ohne Temp-Kopie: [{workingPath}]")
|
||||
End If
|
||||
|
||||
result.Success = True
|
||||
Return result
|
||||
|
||||
Catch ex As Exception
|
||||
result.ErrorMessage = $"Unerwarteter Fehler: {ex.Message}"
|
||||
_Logger.Error($"❌ ProcessDocumentPath: {ex.Message}")
|
||||
_Logger.Error(ex)
|
||||
|
||||
' Cleanup bei Exception
|
||||
If result.WasMapped Then
|
||||
UnmapDrive()
|
||||
End If
|
||||
|
||||
Return result
|
||||
End Try
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Versucht ein Netzlaufwerk zu mappen
|
||||
''' </summary>
|
||||
Private Function TryMapNetworkDrive(sourcePath As String, options As DocumentPathOptions) As MappingResult
|
||||
Dim result As New MappingResult With {.Success = False}
|
||||
|
||||
Try
|
||||
' Prüfen ob Pfad mit WMSUFFIX beginnt
|
||||
If Not sourcePath.StartsWith(options.WMSuffix, StringComparison.OrdinalIgnoreCase) Then
|
||||
_Logger.Debug($"📄 Pfad beginnt nicht mit WMSUFFIX - kein Mapping erforderlich")
|
||||
Return result
|
||||
End If
|
||||
|
||||
_Logger.Debug($"📂 WMSUFFIX erkannt - starte Laufwerks-Mapping")
|
||||
|
||||
' Laufwerk mappen
|
||||
Dim mappedDrive As String = ""
|
||||
|
||||
If Not String.IsNullOrEmpty(options.SpecificDrive) AndAlso options.SpecificDrive.Length = 1 Then
|
||||
' Spezifisches Laufwerk
|
||||
If _clsmapDrive.MapSpecificDrive(options.SpecificDrive, options.DriveBlacklist, options.WMSuffix) Then
|
||||
mappedDrive = options.SpecificDrive & ":"
|
||||
End If
|
||||
Else
|
||||
' Automatisches Mapping
|
||||
mappedDrive = _clsmapDrive.MapDriveAutomatic(options.DriveBlacklist, options.WMSuffix)
|
||||
End If
|
||||
|
||||
If String.IsNullOrEmpty(mappedDrive) Then
|
||||
_Logger.Warn("⚠️ Kein Laufwerk gemappt")
|
||||
Return result
|
||||
End If
|
||||
|
||||
' Pfad umschreiben
|
||||
Dim relativePath As String = sourcePath.Substring(options.WMSuffix.Length)
|
||||
If relativePath.StartsWith("\") Then
|
||||
relativePath = relativePath.Substring(1)
|
||||
End If
|
||||
|
||||
Dim mappedPath As String = mappedDrive.TrimEnd(":"c, "\"c) & ":\" & relativePath
|
||||
|
||||
_Logger.Debug($"📄 Original: [{sourcePath}]")
|
||||
_Logger.Debug($"📄 Gemappt: [{mappedPath}]")
|
||||
|
||||
result.Success = True
|
||||
result.DriveLetter = mappedDrive
|
||||
result.MappedPath = mappedPath
|
||||
Return result
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Error($"Fehler beim Mapping: {ex.Message}")
|
||||
_Logger.Error(ex)
|
||||
Return result
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function CopyToTempFolder(sourcePath As String, tempFolder As String) As TempCopyResult
|
||||
Dim result As New TempCopyResult With {.Success = False}
|
||||
|
||||
Try
|
||||
Dim configuredTempFolder As String = tempFolder
|
||||
Dim globalTempFolder As String = TEMP_DOCUMENT_FOLDER
|
||||
|
||||
' Temp-Ordner validieren/initialisieren (kann tempFolder per ByRef setzen)
|
||||
If Not EnsureTempFolder(tempFolder, result.ErrorMessage) Then
|
||||
_Logger.Warn($"⚠️ {result.ErrorMessage}")
|
||||
_Logger.Warn($"[TempCopy] InputTemp=[{If(String.IsNullOrWhiteSpace(configuredTempFolder), "<leer>", configuredTempFolder)}], GlobalTemp=[{If(String.IsNullOrWhiteSpace(globalTempFolder), "<leer>", globalTempFolder)}]")
|
||||
Return result
|
||||
End If
|
||||
|
||||
' NEU: Effektiven Zielordner immer transparent loggen
|
||||
_Logger.Info($"[TempCopy] Effektiver Temp-Ordner: [{tempFolder}]")
|
||||
_Logger.Debug($"[TempCopy] InputTemp=[{If(String.IsNullOrWhiteSpace(configuredTempFolder), "<leer>", configuredTempFolder)}], GlobalTemp=[{If(String.IsNullOrWhiteSpace(globalTempFolder), "<leer>", globalTempFolder)}]")
|
||||
|
||||
' Eindeutigen Dateinamen generieren
|
||||
Dim originalFileName As String = Path.GetFileName(sourcePath)
|
||||
Dim fileNameWithoutExt As String = Path.GetFileNameWithoutExtension(originalFileName)
|
||||
Dim extension As String = Path.GetExtension(originalFileName)
|
||||
Dim timestamp As String = DateTime.Now.ToString("yyyyMMdd_HHmmss_fff")
|
||||
Dim uniqueFileName As String = $"{fileNameWithoutExt}_{timestamp}{extension}"
|
||||
Dim targetPath As String = Path.Combine(tempFolder, uniqueFileName)
|
||||
|
||||
_Logger.Debug($"📄 Kopiere nach Temp:")
|
||||
_Logger.Debug($" Von: [{sourcePath}]")
|
||||
_Logger.Debug($" Nach: [{targetPath}]")
|
||||
|
||||
File.Copy(sourcePath, targetPath, overwrite:=True)
|
||||
|
||||
result.Success = True
|
||||
result.TempPath = targetPath
|
||||
result.TempFileName = uniqueFileName
|
||||
Return result
|
||||
|
||||
Catch ex As Exception
|
||||
result.ErrorMessage = $"Fehler beim Kopieren: {ex.Message}"
|
||||
_Logger.Error($"❌ {result.ErrorMessage}")
|
||||
_Logger.Error(ex)
|
||||
Return result
|
||||
End Try
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Trennt das gemappte Laufwerk
|
||||
''' </summary>
|
||||
Public Sub UnmapDrive()
|
||||
If Not String.IsNullOrEmpty(_mappedDrive) Then
|
||||
Try
|
||||
If _clsmapDrive.DisconnectNetworkDrive(_mappedDrive, force:=True) Then
|
||||
_Logger.Info($"🔌 Laufwerk {_mappedDrive} getrennt")
|
||||
Else
|
||||
_Logger.Warn($"⚠️ Warnung beim Trennen von {_mappedDrive}")
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_Logger.Debug($"Fehler beim Trennen von {_mappedDrive}: {ex.Message}")
|
||||
Finally
|
||||
_mappedDrive = ""
|
||||
End Try
|
||||
End If
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' Cleanup-Methode (z.B. beim Schließen des Forms)
|
||||
''' </summary>
|
||||
Public Sub Cleanup()
|
||||
UnmapDrive()
|
||||
End Sub
|
||||
|
||||
#Region "Nested Classes für Optionen und Ergebnisse"
|
||||
|
||||
''' <summary>
|
||||
''' Optionen für die Dokumentenpfad-Verarbeitung
|
||||
''' </summary>
|
||||
Public Class DocumentPathOptions
|
||||
''' <summary>Soll Laufwerks-Mapping versucht werden?</summary>
|
||||
Public Property EnableMapping As Boolean = False
|
||||
|
||||
''' <summary>WMSUFFIX für Mapping-Erkennung (z.B. "\\windream\objects")</summary>
|
||||
Public Property WMSuffix As String = ""
|
||||
|
||||
''' <summary>Spezifischer Laufwerksbuchstabe (z.B. "V") oder leer für automatisch</summary>
|
||||
Public Property SpecificDrive As String = ""
|
||||
|
||||
''' <summary>Blacklist für Laufwerksbuchstaben (z.B. "Y,M,V")</summary>
|
||||
Public Property DriveBlacklist As String = ""
|
||||
|
||||
''' <summary>Soll Datei in Temp kopiert werden?</summary>
|
||||
Public Property CopyToTemp As Boolean = False
|
||||
|
||||
''' <summary>Temp-Ordner-Pfad</summary>
|
||||
Public Property TempFolder As String = ""
|
||||
|
||||
''' <summary>Laufwerk nach erfolgreicher Temp-Kopie unmappen?</summary>
|
||||
Public Property UnmapAfterCopy As Boolean = True
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' Ergebnis der Dokumentenpfad-Verarbeitung
|
||||
''' </summary>
|
||||
Public Class DocumentPathResult
|
||||
Public Property Success As Boolean
|
||||
Public Property SourcePath As String
|
||||
Public Property FinalPath As String
|
||||
Public Property ErrorMessage As String
|
||||
Public Property WasMapped As Boolean
|
||||
Public Property MappedDrive As String
|
||||
Public Property WasCopiedToTemp As Boolean
|
||||
Public Property TempPath As String
|
||||
End Class
|
||||
|
||||
Private Class MappingResult
|
||||
Public Property Success As Boolean
|
||||
Public Property DriveLetter As String
|
||||
Public Property MappedPath As String
|
||||
End Class
|
||||
|
||||
Private Class TempCopyResult
|
||||
Public Property Success As Boolean
|
||||
Public Property TempPath As String
|
||||
Public Property TempFileName As String
|
||||
Public Property ErrorMessage As String
|
||||
End Class
|
||||
|
||||
#End Region
|
||||
|
||||
End Class
|
||||
Reference in New Issue
Block a user