Browse Source

Auto-Organize: Fix PathTooLongException due to long EpisodeTitle

Especially with Multi-Episodes, the EpisodeTitle can become quite long,
since all comprised titles get concatenated into it.
By default, the EpisodeTitle is included in the single and multi-episode
naming patterns and this in turn can quickly lead to a
PathTooLongException.
This fix tries to keep as much as possible from the title string while
keeping the final path within the allowed limit.
softworkz 10 năm trước cách đây
mục cha
commit
f7636a6b29

+ 26 - 6
MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs

@@ -435,7 +435,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
 
             var newPath = GetSeasonFolderPath(series, seasonNumber, options);
 
-            var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options);
+            var episodeFileName = GetEpisodeFileName(newPath.Length, sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options);
 
             newPath = Path.Combine(newPath, episodeFileName);
 
@@ -492,7 +492,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
             return Path.Combine(path, _fileSystem.GetValidFilename(seasonFolderName));
         }
 
-        private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options)
+        private string GetEpisodeFileName(int destPathLength, string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options)
         {
             seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
             episodeTitle = _fileSystem.GetValidFilename(episodeTitle).Trim();
@@ -508,9 +508,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
                 .Replace("%0s", seasonNumber.ToString("00", _usCulture))
                 .Replace("%00s", seasonNumber.ToString("000", _usCulture))
                 .Replace("%ext", sourceExtension)
-                .Replace("%en", episodeTitle)
-                .Replace("%e.n", episodeTitle.Replace(" ", "."))
-                .Replace("%e_n", episodeTitle.Replace(" ", "_"));
+                .Replace("%en", "%#1")
+                .Replace("%e.n", "%#2")
+                .Replace("%e_n", "%#3");
 
             if (endingEpisodeNumber.HasValue)
             {
@@ -519,9 +519,29 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
                 .Replace("%00ed", endingEpisodeNumber.Value.ToString("000", _usCulture));
             }
 
-            return result.Replace("%e", episodeNumber.ToString(_usCulture))
+            result = result.Replace("%e", episodeNumber.ToString(_usCulture))
                 .Replace("%0e", episodeNumber.ToString("00", _usCulture))
                 .Replace("%00e", episodeNumber.ToString("000", _usCulture));
+
+            // Add +1 because it is unsure if destpathlength includes a trailing backslash
+            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)
+            int maxRemainingTitleLength = 256 - currentTotalLength + 3;
+            string shortenedEpisodeTitle = string.Empty;
+
+            if (maxRemainingTitleLength > 5)
+            {
+                // A title with fewer than 5 letters wouldn't be of much value
+                shortenedEpisodeTitle = episodeTitle.Substring(0, Math.Min(maxRemainingTitleLength, episodeTitle.Length));
+            }
+
+            return result.Replace("%#1", shortenedEpisodeTitle)
+                .Replace("%#2", shortenedEpisodeTitle.Replace(" ", "."))
+                .Replace("%#3", shortenedEpisodeTitle.Replace(" ", "_"));
+
         }
 
         private bool IsSameEpisode(string sourcePath, string newPath)