diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 38a5d7e98..38fe0ecb7 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -123,35 +123,32 @@ namespace MediaBrowser.Providers.Manager new[] { GetCacheKeyPath(item, type, mimeType, internalCacheKey) } : GetSavePaths(item, type, imageIndex, mimeType, saveLocally); + var retryPaths = !string.IsNullOrEmpty(internalCacheKey) ? + new[] { GetCacheKeyPath(item, type, mimeType, internalCacheKey) } : + GetSavePaths(item, type, imageIndex, mimeType, false); + // If there are more than one output paths, the stream will need to be seekable - if (paths.Length > 1 && !source.CanSeek) + var memoryStream = new MemoryStream(); + using (source) { - var memoryStream = new MemoryStream(); - using (source) - { - await source.CopyToAsync(memoryStream).ConfigureAwait(false); - } - memoryStream.Position = 0; - source = memoryStream; + await source.CopyToAsync(memoryStream).ConfigureAwait(false); } + source = memoryStream; + var currentPath = GetCurrentImagePath(item, type, index); using (source) { - var isFirst = true; + var currentPathIndex = 0; foreach (var path in paths) { - // Seek back to the beginning - if (!isFirst) - { - source.Position = 0; - } + source.Position = 0; - await SaveImageToLocation(source, path, cancellationToken).ConfigureAwait(false); + await SaveImageToLocation(source, path, retryPaths[currentPathIndex], cancellationToken).ConfigureAwait(false); - isFirst = false; + currentPathIndex++; } } @@ -185,6 +182,30 @@ namespace MediaBrowser.Providers.Manager } } + private async Task SaveImageToLocation(Stream source, string path, string retryPath, CancellationToken cancellationToken) + { + try + { + await SaveImageToLocation(source, path, cancellationToken).ConfigureAwait(false); + } + catch (UnauthorizedAccessException) + { + var retry = !string.Equals(path, retryPath, StringComparison.OrdinalIgnoreCase); + + if (retry) + { + _logger.Error("UnauthorizedAccessException - Access to path {0} is denied. Will retry saving to {1}", path, retryPath); + } + else + { + throw; + } + } + + source.Position = 0; + await SaveImageToLocation(source, retryPath, cancellationToken).ConfigureAwait(false); + } + private string GetCacheKeyPath(IHasImages item, ImageType type, string mimeType, string key) { var extension = MimeTypes.ToExtension(mimeType); @@ -209,7 +230,7 @@ namespace MediaBrowser.Providers.Manager try { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); // If the file is currently hidden we'll have to remove that or the save will fail var file = new FileInfo(path); diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs index 0321af66b..2e9d42f49 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs @@ -87,6 +87,7 @@ namespace MediaBrowser.Server.Implementations.Channels const int currentRefreshLevel = 1; var maxRefreshLevel = features.AutoRefreshLevels ?? 0; + maxRefreshLevel = Math.Max(maxRefreshLevel, 2); if (maxRefreshLevel > 0) { diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index 968e4ef1d..45b159574 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -203,10 +203,12 @@ namespace MediaBrowser.Server.Implementations.Configuration && !string.Equals(Configuration.ItemsByNamePath ?? string.Empty, newPath)) { // Validate - if (!_fileSystem.DirectoryExists(newPath)) + if (!_fileSystem.DirectoryExists(newPath)) { throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath)); } + + EnsureWriteAccess(newPath); } } @@ -223,13 +225,23 @@ namespace MediaBrowser.Server.Implementations.Configuration && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath)) { // Validate - if (!_fileSystem.DirectoryExists(newPath)) + if (!_fileSystem.DirectoryExists(newPath)) { throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath)); } + + EnsureWriteAccess(newPath); } } + private void EnsureWriteAccess(string path) + { + var file = Path.Combine(path, Guid.NewGuid().ToString()); + + _fileSystem.WriteAllText(file, string.Empty); + _fileSystem.DeleteFile(file); + } + public void DisableMetadataService(string service) { DisableMetadataService(typeof(Movie), Configuration, service);