Auto-Organize: Fix PathTooLongException due to long EpisodeTitle #2

This commit is contained in:
softworkz 2015-10-02 20:44:30 +02:00
parent f7636a6b29
commit 4a235bd4bd

View File

@ -435,20 +435,28 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var newPath = GetSeasonFolderPath(series, seasonNumber, options); var newPath = GetSeasonFolderPath(series, seasonNumber, options);
var episodeFileName = GetEpisodeFileName(newPath.Length, sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options); // MAX_PATH - trailing <NULL> charachter - drive component: 260 - 1 - 3 = 256
// Usually newPath would include the drive component, but use 256 to be sure
var maxFilenameLength = 256 - newPath.Length;
newPath = Path.Combine(newPath, episodeFileName); if (!newPath.EndsWith(@"\"))
// Try to account for windows limitations by removing the episode title
if (newPath.Length > 255)
{ {
var extension = Path.GetExtension(episodeFileName); // Remove 1 for missing backslash combining path and filename
var fileName = Path.GetFileNameWithoutExtension(episodeFileName); maxFilenameLength--;
fileName = fileName.Replace(episode.Name, string.Empty, StringComparison.OrdinalIgnoreCase); }
episodeFileName = Path.ChangeExtension(fileName, extension);
// Remove additional 4 chars to prevent PathTooLongException for downloaded subtitles (eg. filename.ext.eng.srt)
maxFilenameLength -= 4;
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options, maxFilenameLength);
if (string.IsNullOrEmpty(episodeFileName))
{
// cause failure
return string.Empty;
}
newPath = Path.Combine(newPath, episodeFileName); newPath = Path.Combine(newPath, episodeFileName);
}
return newPath; return newPath;
} }
@ -492,7 +500,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return Path.Combine(path, _fileSystem.GetValidFilename(seasonFolderName)); return Path.Combine(path, _fileSystem.GetValidFilename(seasonFolderName));
} }
private string GetEpisodeFileName(int destPathLength, string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options) private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options, int? maxLength)
{ {
seriesName = _fileSystem.GetValidFilename(seriesName).Trim(); seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
episodeTitle = _fileSystem.GetValidFilename(episodeTitle).Trim(); episodeTitle = _fileSystem.GetValidFilename(episodeTitle).Trim();
@ -523,13 +531,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
.Replace("%0e", episodeNumber.ToString("00", _usCulture)) .Replace("%0e", episodeNumber.ToString("00", _usCulture))
.Replace("%00e", episodeNumber.ToString("000", _usCulture)); .Replace("%00e", episodeNumber.ToString("000", _usCulture));
// Add +1 because it is unsure if destpathlength includes a trailing backslash if (maxLength.HasValue && result.Contains("%#"))
int currentTotalLength = destPathLength + 1 + result.Length; {
// MAX_PATH - trailing <NULL> charachter - drive component: 260 - 1 - 3 = 256
// Usually maxRemainingTitleLength would include the drive component, but use 256 to be sure
// Substract 3 for the temp token length (%#1, %#2 or %#3) // Substract 3 for the temp token length (%#1, %#2 or %#3)
int maxRemainingTitleLength = 256 - currentTotalLength + 3; int maxRemainingTitleLength = maxLength.Value - result.Length + 3;
string shortenedEpisodeTitle = string.Empty; string shortenedEpisodeTitle = string.Empty;
if (maxRemainingTitleLength > 5) if (maxRemainingTitleLength > 5)
@ -538,10 +543,21 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
shortenedEpisodeTitle = episodeTitle.Substring(0, Math.Min(maxRemainingTitleLength, episodeTitle.Length)); shortenedEpisodeTitle = episodeTitle.Substring(0, Math.Min(maxRemainingTitleLength, episodeTitle.Length));
} }
return result.Replace("%#1", shortenedEpisodeTitle) result = result.Replace("%#1", shortenedEpisodeTitle)
.Replace("%#2", shortenedEpisodeTitle.Replace(" ", ".")) .Replace("%#2", shortenedEpisodeTitle.Replace(" ", "."))
.Replace("%#3", shortenedEpisodeTitle.Replace(" ", "_")); .Replace("%#3", shortenedEpisodeTitle.Replace(" ", "_"));
}
if (maxLength.HasValue && result.Length > maxLength.Value)
{
// There may be cases where reducing the title length may still not be sufficient to
// stay below maxLength
var msg = string.Format("Unable to generate an episode file name shorter than {0} characters to constrain to the max path limit", maxLength);
_logger.Warn(msg);
return string.Empty;
}
return result;
} }
private bool IsSameEpisode(string sourcePath, string newPath) private bool IsSameEpisode(string sourcePath, string newPath)