diff --git a/Modules.Filesystem/File.vb b/Modules.Filesystem/File.vb index 344daf4c..e29f65d4 100644 --- a/Modules.Filesystem/File.vb +++ b/Modules.Filesystem/File.vb @@ -23,8 +23,8 @@ Imports DigitalData.Modules.Logging ''' ''' Public Class File - Private ReadOnly _logger As Logger - Private ReadOnly _logConfig As LogConfig + Private ReadOnly _Logger As Logger + Private ReadOnly _LogConfig As LogConfig Private ReadOnly _invalidFilenameChars As String Private ReadOnly _invalidPathChars As String @@ -32,36 +32,42 @@ Public Class File Private Const REGEX_CLEAN_FILENAME As String = "[\\/:""<>|\b\0\r\n\t]" Private Const REGEX_CLEAN_PATH As String = "[:""<>|\b\0\r\n\t]" + ' The limit enforced by windows for filenpaths is 260, + ' so we use a slightly smaller number to have some Error margin. + ' + ' Source: https://docs.microsoft.com/de-de/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#maximum-path-length-limitation + Private Const MAX_FILE_PATH_LENGTH = 250 + Private Const FILE_NAME_ACCESS_TEST = "accessTest.txt" Public Sub New(LogConfig As LogConfig) - _logConfig = LogConfig - _logger = LogConfig.GetLogger() + _LogConfig = LogConfig + _Logger = LogConfig.GetLogger() _invalidFilenameChars = String.Join("", Path.GetInvalidFileNameChars()) _invalidPathChars = String.Join("", Path.GetInvalidPathChars()) End Sub Public Function GetCleanFilename(FileName As String) As String - _logger.Debug("Filename before cleaning: [{0}]", FileName) + _Logger.Debug("Filename before cleaning: [{0}]", FileName) Dim oCleanName As String = FileName oCleanName = Regex.Replace(oCleanName, _invalidFilenameChars, String.Empty) oCleanName = Regex.Replace(oCleanName, REGEX_CLEAN_FILENAME, String.Empty, RegexOptions.Singleline) - _logger.Debug("Filename after cleaning: [{0}]", oCleanName) + _Logger.Debug("Filename after cleaning: [{0}]", oCleanName) Return oCleanName End Function Public Function GetCleanPath(FilePath As String) As String - _logger.Debug("Path before cleaning: [{0}]", FilePath) + _Logger.Debug("Path before cleaning: [{0}]", FilePath) Dim oCleanName As String = FilePath oCleanName = Regex.Replace(oCleanName, _invalidPathChars, String.Empty) oCleanName = Regex.Replace(oCleanName, REGEX_CLEAN_PATH, String.Empty, RegexOptions.Singleline) - _logger.Debug("Path after cleaning: [{0}]", oCleanName) + _Logger.Debug("Path after cleaning: [{0}]", oCleanName) Return oCleanName End Function @@ -118,20 +124,32 @@ Public Class File oFileVersion = 1 End If + ' Shorten the filename (only filename, without extension or version) + ' by cutting the length in half. This should work no matter how long the path and/or filename are. + If oFileName.Length > MAX_FILE_PATH_LENGTH Then + _Logger.Info("Filename is too long. Filename will be cut to prevent further errors.") + _Logger.Info("Original Filename is: {0}", oFileNameWithoutExtension) + Dim oNewLength As Integer = Math.Round(oFileNameWithoutExtension.Length / 2) + Dim oNewFileNameWithoutExtension = oFileNameWithoutExtension.Substring(0, oNewLength) + _Logger.Info("New Filename will be: {0}", oNewFileNameWithoutExtension) + + oFileNameWithoutExtension = oNewFileNameWithoutExtension + End If + ' while file exists, increment version Do oFinalFileName = Path.Combine(oDestinationDir, GetFilenameWithVersion(oFileNameWithoutExtension, oVersionSeparator, oFileVersion, oExtension)) - _logger.Debug("Intermediate Filename is {0}", oFinalFileName) - _logger.Debug("File version: {0}", oFileVersion) + _Logger.Debug("Intermediate Filename is {0}", oFinalFileName) + _Logger.Debug("File version: {0}", oFileVersion) oFileVersion += 1 Loop While (IO.File.Exists(oFinalFileName)) - _logger.Debug("Final Filename is {0}", oFinalFileName) + _Logger.Debug("Final Filename is {0}", oFinalFileName) Return oFinalFileName Catch ex As Exception - _logger.Warn("Filename {0} could not be versioned. Original filename will be returned!", Destination) - _logger.Error(ex) + _Logger.Warn("Filename {0} could not be versioned. Original filename will be returned!", Destination) + _Logger.Error(ex) Return Destination End Try End Function @@ -177,29 +195,29 @@ Public Class File ToList() If oFiles.Count = 0 Then - _logger.Debug("No files found that match the criterias.") + _Logger.Debug("No files found that match the criterias.") Return True End If - _logger.Debug("Deleting old files (Found {0}).", oFiles.Count) + _Logger.Debug("Deleting old files (Found {0}).", oFiles.Count) For Each oFile As FileInfo In oFiles Try oFile.Delete() Catch ex As Exception If ContinueOnError = False Then - _logger.Warn("Deleting files was aborted at file {0}.", oFile.FullName) + _Logger.Warn("Deleting files was aborted at file {0}.", oFile.FullName) Return False End If oUnableToDeleteCounter = oUnableToDeleteCounter + 1 - _logger.Warn("File {0} could not be deleted!") + _Logger.Warn("File {0} could not be deleted!") End Try Next If oUnableToDeleteCounter > 0 Then - _logger.Debug("Old files partially removed. {0} files could not be removed.", oUnableToDeleteCounter) + _Logger.Debug("Old files partially removed. {0} files could not be removed.", oUnableToDeleteCounter) Else - _logger.Debug("Old files removed.") + _Logger.Debug("Old files removed.") End If Return True @@ -256,27 +274,27 @@ Public Class File Public Function CreateDirectory(DirectoryPath As String, Optional TestWriteAccess As Boolean = True) As String Dim oFinalPath As String If Directory.Exists(DirectoryPath) Then - _logger.Debug("Directory {0} already exists. Skipping.", DirectoryPath) + _Logger.Debug("Directory {0} already exists. Skipping.", DirectoryPath) oFinalPath = DirectoryPath Else Try Directory.CreateDirectory(DirectoryPath) oFinalPath = DirectoryPath Catch ex As Exception - _logger.Error(ex) - _logger.Warn("Directory {0} could not be created. Temp path will be used instead.", DirectoryPath) + _Logger.Error(ex) + _Logger.Warn("Directory {0} could not be created. Temp path will be used instead.", DirectoryPath) oFinalPath = Path.GetTempPath() End Try End If If TestWriteAccess AndAlso Not TestPathIsWritable(DirectoryPath) Then - _logger.Warn("Directory {0} is not writable. Temp path will be used instead.", DirectoryPath) + _Logger.Warn("Directory {0} is not writable. Temp path will be used instead.", DirectoryPath) oFinalPath = Path.GetTempPath() Else oFinalPath = DirectoryPath End If - _logger.Debug("Using path {0}", oFinalPath) + _Logger.Debug("Using path {0}", oFinalPath) Return oFinalPath End Function