tightened up image saving to reduce knowledge of file names

pull/702/head
Luke Pulverenti 11 years ago
parent ac7d6256f4
commit 8a1b12b7d8

@ -760,145 +760,45 @@ namespace MediaBrowser.Api.Images
var bytes = Convert.FromBase64String(text);
// Validate first
using (var memoryStream = new MemoryStream(bytes))
using (var validationStream = new MemoryStream(bytes))
{
using (var image = Image.FromStream(memoryStream))
using (var image = Image.FromStream(validationStream))
{
Logger.Info("New image is {0}x{1}", image.Width, image.Height);
}
}
string filename;
var memoryStream = new MemoryStream(bytes);
switch (imageType)
{
case ImageType.Art:
filename = "clearart";
break;
case ImageType.Primary:
filename = entity is Episode ? Path.GetFileNameWithoutExtension(entity.Path) : "folder";
break;
case ImageType.Backdrop:
filename = GetBackdropFilenameToSave(entity);
break;
case ImageType.Screenshot:
filename = GetScreenshotFilenameToSave(entity);
break;
default:
filename = imageType.ToString().ToLower();
break;
}
memoryStream.Position = 0;
var imageIndex = 0;
var extension = mimeType.Split(';').First().Split('/').Last();
string oldImagePath;
switch (imageType)
if (imageType == ImageType.Screenshot)
{
case ImageType.Backdrop:
case ImageType.Screenshot:
oldImagePath = null;
break;
default:
oldImagePath = entity.GetImage(imageType);
break;
imageIndex = entity.ScreenshotImagePaths.Count;
}
// Don't save locally if there's no parent (special feature, trailer, etc)
var saveLocally = !(entity is Audio) && entity.Parent != null && !string.IsNullOrEmpty(entity.MetaLocation) || entity is User;
if (imageType != ImageType.Primary)
else if (imageType == ImageType.Backdrop)
{
if (entity is Episode)
{
saveLocally = false;
}
imageIndex = entity.BackdropImagePaths.Count;
}
if (entity.LocationType != LocationType.FileSystem)
{
saveLocally = false;
}
await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, imageIndex, CancellationToken.None).ConfigureAwait(false);
var imagePath = _providerManager.GetSavePath(entity, filename + "." + extension, saveLocally);
var user = entity as User;
// Save to file system
using (var fs = new FileStream(imagePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
if (user != null)
{
await fs.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
}
if (imageType == ImageType.Screenshot)
{
entity.ScreenshotImagePaths.Add(imagePath);
}
else if (imageType == ImageType.Backdrop)
{
entity.BackdropImagePaths.Add(imagePath);
await _userManager.UpdateUser(user).ConfigureAwait(false);
}
else
{
// Set the image
entity.SetImage(imageType, imagePath);
}
// If the new and old paths are different, delete the old one
if (!string.IsNullOrEmpty(oldImagePath) && !oldImagePath.Equals(imagePath, StringComparison.OrdinalIgnoreCase))
{
File.Delete(oldImagePath);
await _libraryManager.UpdateItem(entity, ItemUpdateType.ImageUpdate, CancellationToken.None)
.ConfigureAwait(false);
}
// Directory watchers should repeat this, but do a quick refresh first
await entity.RefreshMetadata(CancellationToken.None, forceSave: true, allowSlowProviders: false).ConfigureAwait(false);
await entity.RefreshMetadata(CancellationToken.None, allowSlowProviders: false).ConfigureAwait(false);
}
}
/// <summary>
/// Gets the backdrop filename to save.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
private string GetBackdropFilenameToSave(BaseItem item)
{
var paths = item.BackdropImagePaths.ToList();
if (!paths.Any(i => string.Equals(Path.GetFileNameWithoutExtension(i), "backdrop", StringComparison.OrdinalIgnoreCase)))
{
return "screenshot";
}
var index = 1;
while (paths.Any(i => string.Equals(Path.GetFileNameWithoutExtension(i), "backdrop" + index, StringComparison.OrdinalIgnoreCase)))
{
index++;
}
return "backdrop" + index;
}
/// <summary>
/// Gets the screenshot filename to save.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
private string GetScreenshotFilenameToSave(BaseItem item)
{
var paths = item.ScreenshotImagePaths.ToList();
if (!paths.Any(i => string.Equals(Path.GetFileNameWithoutExtension(i), "screenshot", StringComparison.OrdinalIgnoreCase)))
{
return "screenshot";
}
var index = 1;
while (paths.Any(i => string.Equals(Path.GetFileNameWithoutExtension(i), "screenshot" + index, StringComparison.OrdinalIgnoreCase)))
{
index++;
}
return "screenshot" + index;
}
}
}

@ -104,6 +104,92 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
return client;
}
public async Task<HttpResponseInfo> GetResponse(HttpRequestOptions options)
{
ValidateParams(options.Url, options.CancellationToken);
options.CancellationToken.ThrowIfCancellationRequested();
var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < 30)
{
throw new HttpException(string.Format("Cancelling connection to {0} due to a previous timeout.", options.Url)) { IsTimedOut = true };
}
using (var message = GetHttpRequestMessage(options))
{
if (options.ResourcePool != null)
{
await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
}
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < 30)
{
if (options.ResourcePool != null)
{
options.ResourcePool.Release();
}
throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
}
_logger.Info("HttpClientManager.Get url: {0}", options.Url);
try
{
options.CancellationToken.ThrowIfCancellationRequested();
var response = await client.HttpClient.SendAsync(message, HttpCompletionOption.ResponseContentRead, options.CancellationToken).ConfigureAwait(false);
EnsureSuccessStatusCode(response);
options.CancellationToken.ThrowIfCancellationRequested();
return new HttpResponseInfo
{
Content = await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
StatusCode = response.StatusCode,
ContentType = response.Content.Headers.ContentType.MediaType
};
}
catch (OperationCanceledException ex)
{
var exception = GetCancellationException(options.Url, options.CancellationToken, ex);
var httpException = exception as HttpException;
if (httpException != null && httpException.IsTimedOut)
{
client.LastTimeout = DateTime.UtcNow;
}
throw exception;
}
catch (HttpRequestException ex)
{
_logger.ErrorException("Error getting response from " + options.Url, ex);
throw new HttpException(ex.Message, ex);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting response from " + options.Url, ex);
throw;
}
finally
{
if (options.ResourcePool != null)
{
options.ResourcePool.Release();
}
}
}
}
/// <summary>
/// Performs a GET request and returns the resulting stream
/// </summary>

@ -1,46 +0,0 @@
using System;
namespace MediaBrowser.Common.Implementations.HttpClientManager
{
/// <summary>
/// Class HttpResponseOutput
/// </summary>
public class HttpResponseInfo
{
/// <summary>
/// Gets or sets the URL.
/// </summary>
/// <value>The URL.</value>
public string Url { get; set; }
/// <summary>
/// Gets or sets the etag.
/// </summary>
/// <value>The etag.</value>
public string Etag { get; set; }
/// <summary>
/// Gets or sets the last modified.
/// </summary>
/// <value>The last modified.</value>
public DateTime? LastModified { get; set; }
/// <summary>
/// Gets or sets the expires.
/// </summary>
/// <value>The expires.</value>
public DateTime? Expires { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [must revalidate].
/// </summary>
/// <value><c>true</c> if [must revalidate]; otherwise, <c>false</c>.</value>
public bool MustRevalidate { get; set; }
/// <summary>
/// Gets or sets the request date.
/// </summary>
/// <value>The request date.</value>
public DateTime RequestDate { get; set; }
}
}

@ -66,7 +66,6 @@
<Compile Include="Configuration\BaseConfigurationManager.cs" />
<Compile Include="HttpClientManager\HttpClientInfo.cs" />
<Compile Include="HttpClientManager\HttpClientManager.cs" />
<Compile Include="HttpClientManager\HttpResponseInfo.cs" />
<Compile Include="Logging\LogHelper.cs" />
<Compile Include="Logging\NLogger.cs" />
<Compile Include="Logging\NlogManager.cs" />

@ -74,6 +74,7 @@
<Compile Include="Net\BasePeriodicWebSocketListener.cs" />
<Compile Include="Configuration\IApplicationPaths.cs" />
<Compile Include="Net\HttpRequestOptions.cs" />
<Compile Include="Net\HttpResponseInfo.cs" />
<Compile Include="Net\IHasResultFactory.cs" />
<Compile Include="Net\IHttpResultFactory.cs" />
<Compile Include="Net\IServerManager.cs" />

@ -0,0 +1,29 @@
using System.IO;
using System.Net;
namespace MediaBrowser.Common.Net
{
/// <summary>
/// Class HttpResponseInfo
/// </summary>
public class HttpResponseInfo
{
/// <summary>
/// Gets or sets the type of the content.
/// </summary>
/// <value>The type of the content.</value>
public string ContentType { get; set; }
/// <summary>
/// Gets or sets the content.
/// </summary>
/// <value>The content.</value>
public Stream Content { get; set; }
/// <summary>
/// Gets or sets the status code.
/// </summary>
/// <value>The status code.</value>
public HttpStatusCode StatusCode { get; set; }
}
}

@ -11,6 +11,13 @@ namespace MediaBrowser.Common.Net
/// </summary>
public interface IHttpClient : IDisposable
{
/// <summary>
/// Gets the response.
/// </summary>
/// <param name="options">The options.</param>
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetResponse(HttpRequestOptions options);
/// <summary>
/// Performs a GET request and returns the resulting stream
/// </summary>

@ -798,6 +798,9 @@ namespace MediaBrowser.Controller.Entities
});
await ((Folder)child).ValidateChildren(innerProgress, cancellationToken, recursive, forceRefreshMetadata).ConfigureAwait(false);
// Some folder providers are unable to refresh until children have been refreshed.
await child.RefreshMetadata(cancellationToken, resetResolveArgs: false).ConfigureAwait(false);
}
else
{

@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@ -12,64 +13,47 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
public interface IProviderManager
{
/// <summary>
/// Downloads the and save image.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="source">The source.</param>
/// <param name="targetName">Name of the target.</param>
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, bool saveLocally, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, bool saveLocally,
SemaphoreSlim resourcePool, CancellationToken cancellationToken);
/// <summary>
/// Saves the image.
/// Executes the metadata providers.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="source">The source.</param>
/// <param name="targetName">Name of the target.</param>
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns>
Task<string> SaveImage(BaseItem item, Stream source, string targetName, bool saveLocally, CancellationToken cancellationToken);
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
/// <returns>Task{System.Boolean}.</returns>
Task<ItemUpdateType?> ExecuteMetadataProviders(BaseItem item, CancellationToken cancellationToken, bool force = false, bool allowSlowProviders = true);
/// <summary>
/// Saves to library filesystem.
/// Saves the image.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="path">The path.</param>
/// <param name="dataToSave">The data to save.</param>
/// <param name="url">The URL.</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
Task SaveToLibraryFilesystem(BaseItem item, string path, Stream dataToSave, CancellationToken cancellationToken);
Task SaveImage(BaseItem item, string url, SemaphoreSlim resourcePool, ImageType type, int? imageIndex, CancellationToken cancellationToken);
/// <summary>
/// Executes the metadata providers.
/// Saves the image.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="source">The source.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
/// <returns>Task{System.Boolean}.</returns>
Task<ItemUpdateType?> ExecuteMetadataProviders(BaseItem item, CancellationToken cancellationToken, bool force = false, bool allowSlowProviders = true);
/// <returns>Task.</returns>
Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken);
/// <summary>
/// Adds the metadata providers.
/// </summary>
/// <param name="providers">The providers.</param>
void AddParts(IEnumerable<BaseMetadataProvider> providers);
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="targetFileName">Name of the target file.</param>
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
/// <returns>System.String.</returns>
string GetSavePath(BaseItem item, string targetFileName, bool saveLocally);
}
}

@ -303,9 +303,6 @@ namespace MediaBrowser.Providers.Movies
cancellationToken.ThrowIfCancellationRequested();
var saveLocal = ConfigurationManager.Configuration.SaveLocalMeta &&
item.LocationType == LocationType.FileSystem;
string path;
var hd = ConfigurationManager.Configuration.DownloadHDFanArt ? "hd" : "";
@ -322,7 +319,7 @@ namespace MediaBrowser.Providers.Movies
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(item, path, LogoFile, saveLocal, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Logo, null, cancellationToken).ConfigureAwait(false);
}
}
cancellationToken.ThrowIfCancellationRequested();
@ -337,7 +334,8 @@ namespace MediaBrowser.Providers.Movies
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(item, path, ArtFile, saveLocal, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Art, null, cancellationToken)
.ConfigureAwait(false);
}
}
cancellationToken.ThrowIfCancellationRequested();
@ -349,7 +347,8 @@ namespace MediaBrowser.Providers.Movies
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(item, path, DiscFile, saveLocal, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Disc, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -362,7 +361,8 @@ namespace MediaBrowser.Providers.Movies
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(item, path, BannerFile, saveLocal, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Banner, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -375,7 +375,8 @@ namespace MediaBrowser.Providers.Movies
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Thumb, await _providerManager.DownloadAndSaveImage(item, path, ThumbFile, saveLocal, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Thumb, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -393,7 +394,8 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrEmpty(path))
{
item.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(item, path, ("backdrop" + (numBackdrops > 0 ? numBackdrops.ToString(UsCulture) : "") + ".jpg"), saveLocal, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken)
.ConfigureAwait(false);
numBackdrops++;

@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.Movies
return ItemUpdateType.ImageUpdate;
}
}
/// <summary>
/// Gets a value indicating whether [requires internet].
/// </summary>
@ -148,7 +148,7 @@ namespace MediaBrowser.Providers.Movies
{
return false;
}
return base.NeedsRefreshInternal(item, providerInfo);
}
@ -168,7 +168,7 @@ namespace MediaBrowser.Providers.Movies
data = new BaseProviderInfo();
item.ProviderData[Id] = data;
}
var images = await FetchImages(item, item.GetProviderId(MetadataProviders.Tmdb), cancellationToken).ConfigureAwait(false);
var status = await ProcessImages(item, images, cancellationToken).ConfigureAwait(false);
@ -246,7 +246,9 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false);
item.PrimaryImagePath = await _providerManager.SaveImage(item, img, "folder" + Path.GetExtension(poster.file_path), ConfigurationManager.Configuration.SaveLocalMeta && item.LocationType == LocationType.FileSystem, cancellationToken).ConfigureAwait(false);
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -274,7 +276,8 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false);
item.BackdropImagePaths.Add(await _providerManager.SaveImage(item, img, bdName + Path.GetExtension(images.backdrops[i].file_path), ConfigurationManager.Configuration.SaveLocalMeta && item.LocationType == LocationType.FileSystem, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(images.backdrops[i].file_path), ImageType.Backdrop, item.BackdropImagePaths.Count, cancellationToken)
.ConfigureAwait(false);
}
if (item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops)

@ -32,7 +32,7 @@ namespace MediaBrowser.Providers.Movies
/// <summary>
/// The movie db
/// </summary>
private readonly SemaphoreSlim _movieDbResourcePool = new SemaphoreSlim(1,1);
private readonly SemaphoreSlim _movieDbResourcePool = new SemaphoreSlim(1, 1);
internal static MovieDbProvider Current { get; private set; }
@ -158,7 +158,7 @@ namespace MediaBrowser.Providers.Movies
_tmdbSettingsSemaphore.Release();
return _tmdbSettings;
}
try
{
using (var json = await GetMovieDbResponse(new HttpRequestOptions
@ -199,7 +199,13 @@ namespace MediaBrowser.Providers.Movies
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (HasAltMeta(item))
return false;
return false;
// Boxsets require two passes because we need the children to be refreshed
if (item is BoxSet && string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.TmdbCollection)))
{
return true;
}
return base.NeedsRefreshInternal(item, providerInfo);
}
@ -291,19 +297,6 @@ namespace MediaBrowser.Providers.Movies
/// <returns>Task{System.String}.</returns>
public async Task<string> FindId(BaseItem item, int? productionYear, CancellationToken cancellationToken)
{
string id = null;
if (item.LocationType == LocationType.FileSystem)
{
string justName = item.Path != null ? item.Path.Substring(item.Path.LastIndexOf(Path.DirectorySeparatorChar)) : string.Empty;
id = justName.GetAttributeValue("tmdbid");
if (id != null)
{
Logger.Debug("Using tmdb id specified in path.");
return id;
}
}
int? year;
string name = item.Name;
ParseName(name, out name, out year);
@ -320,25 +313,14 @@ namespace MediaBrowser.Providers.Movies
var boxset = item as BoxSet;
if (boxset != null)
{
var firstChild = boxset.Children.FirstOrDefault();
if (firstChild != null)
{
Logger.Debug("MovieDbProvider - Attempting to find boxset ID from: " + firstChild.Name);
string childName;
int? childYear;
ParseName(firstChild.Name, out childName, out childYear);
id = await GetBoxsetIdFromMovie(childName, childYear, language, cancellationToken).ConfigureAwait(false);
if (id != null)
{
Logger.Info("MovieDbProvider - Found Boxset ID: " + id);
}
}
return id;
// See if any movies have a collection id already
return boxset.Children.OfType<Video>()
.Select(i => i.GetProviderId(MetadataProviders.TmdbCollection))
.FirstOrDefault(i => i != null);
}
//nope - search for it
id = await AttemptFindId(name, year, language, cancellationToken).ConfigureAwait(false);
var id = await AttemptFindId(name, year, language, cancellationToken).ConfigureAwait(false);
if (id == null)
{
//try in english if wasn't before
@ -509,7 +491,7 @@ namespace MediaBrowser.Providers.Movies
DateTime r;
//These dates are always in this exact format
if (DateTime.TryParseExact(possible.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
if (DateTime.TryParseExact(possible.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
{
if (Math.Abs(r.Year - year.Value) > 1) // allow a 1 year tolerance on release date
{
@ -708,7 +690,7 @@ namespace MediaBrowser.Providers.Movies
var ourRelease = movieData.releases.countries.FirstOrDefault(c => c.iso_3166_1.Equals(ConfigurationManager.Configuration.MetadataCountryCode, StringComparison.OrdinalIgnoreCase)) ?? new Country();
var usRelease = movieData.releases.countries.FirstOrDefault(c => c.iso_3166_1.Equals("US", StringComparison.OrdinalIgnoreCase)) ?? new Country();
var minimunRelease = movieData.releases.countries.OrderBy(c => c.release_date).FirstOrDefault() ?? new Country();
var ratingPrefix = ConfigurationManager.Configuration.MetadataCountryCode.Equals("us", StringComparison.OrdinalIgnoreCase) ? "" : ConfigurationManager.Configuration.MetadataCountryCode +"-";
var ratingPrefix = ConfigurationManager.Configuration.MetadataCountryCode.Equals("us", StringComparison.OrdinalIgnoreCase) ? "" : ConfigurationManager.Configuration.MetadataCountryCode + "-";
movie.OfficialRating = !string.IsNullOrEmpty(ourRelease.certification)
? ratingPrefix + ourRelease.certification
: !string.IsNullOrEmpty(usRelease.certification)
@ -725,7 +707,7 @@ namespace MediaBrowser.Providers.Movies
movie.ProductionYear = ourRelease.release_date.Year;
}
}
else if(usRelease.release_date != default (DateTime))
else if (usRelease.release_date != default(DateTime))
{
if (usRelease.release_date.Year != 1)
{
@ -733,7 +715,7 @@ namespace MediaBrowser.Providers.Movies
movie.ProductionYear = usRelease.release_date.Year;
}
}
else if (minimunRelease.release_date != default (DateTime))
else if (minimunRelease.release_date != default(DateTime))
{
if (minimunRelease.release_date.Year != 1)
{
@ -1099,7 +1081,7 @@ namespace MediaBrowser.Providers.Movies
/// <value>The total_results.</value>
public int total_results { get; set; }
}
protected class BelongsToCollection
{
public int id { get; set; }

@ -279,13 +279,8 @@ namespace MediaBrowser.Providers.Movies
{
var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var img = await DownloadAndSaveImage(person, tmdbSettings.images.base_url + ConfigurationManager.Configuration.TmdbFetchedProfileSize + profile.file_path,
"folder" + Path.GetExtension(profile.file_path), cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(img))
{
person.PrimaryImagePath = img;
}
await DownloadAndSaveImage(person, tmdbSettings.images.base_url + ConfigurationManager.Configuration.TmdbFetchedProfileSize + profile.file_path,
MimeTypes.GetMimeType(profile.file_path), cancellationToken).ConfigureAwait(false);
}
}
}
@ -300,15 +295,12 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
/// <param name="item">The item.</param>
/// <param name="source">The source.</param>
/// <param name="targetName">Name of the target.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns>
private async Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, CancellationToken cancellationToken)
private async Task DownloadAndSaveImage(BaseItem item, string source, string mimeType, CancellationToken cancellationToken)
{
if (source == null) return null;
//download and save locally (if not already there)
var localPath = Path.Combine(item.MetaLocation, targetName);
if (source == null) return;
using (var sourceStream = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
@ -317,12 +309,11 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false))
{
await ProviderManager.SaveToLibraryFilesystem(item, localPath, sourceStream, cancellationToken).ConfigureAwait(false);
await ProviderManager.SaveImage(item, sourceStream, mimeType, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
Logger.Debug("TmdbPersonProvider downloaded and saved image for {0}", item.Name);
}
return localPath;
}
#region Result Objects

@ -199,7 +199,8 @@ namespace MediaBrowser.Providers.Music
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Disc, await _providerManager.DownloadAndSaveImage(item, path, DiscFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Disc, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -217,7 +218,8 @@ namespace MediaBrowser.Providers.Music
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(item, path, PrimaryFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
}
}

@ -306,7 +306,8 @@ namespace MediaBrowser.Providers.Music
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(item, path, LogoFile, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Logo, null, cancellationToken)
.ConfigureAwait(false);
}
}
cancellationToken.ThrowIfCancellationRequested();
@ -323,7 +324,8 @@ namespace MediaBrowser.Providers.Music
path = node.Value;
if (!string.IsNullOrEmpty(path))
{
item.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(item, path, ("Backdrop" + (numBackdrops > 0 ? numBackdrops.ToString(UsCulture) : "") + ".jpg"), SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken)
.ConfigureAwait(false);
numBackdrops++;
if (numBackdrops >= ConfigurationManager.Configuration.MaxBackdrops) break;
}
@ -343,7 +345,8 @@ namespace MediaBrowser.Providers.Music
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(item, path, ArtFile, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Art, null, cancellationToken)
.ConfigureAwait(false);
}
}
cancellationToken.ThrowIfCancellationRequested();
@ -355,7 +358,8 @@ namespace MediaBrowser.Providers.Music
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(item, path, BannerFile, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Banner, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -368,7 +372,8 @@ namespace MediaBrowser.Providers.Music
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Primary, await _providerManager.DownloadAndSaveImage(item, path, PrimaryFile, SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
}
}

@ -82,13 +82,16 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<Airs_Time>" + SecurityElement.Escape(series.AirTime) + "</Airs_Time>");
}
if (series.AirDays.Count == 7)
if (series.AirDays != null)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape("Daily") + "</Airs_DayOfWeek>");
}
else if (series.AirDays.Count > 0)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</Airs_DayOfWeek>");
if (series.AirDays.Count == 7)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape("Daily") + "</Airs_DayOfWeek>");
}
else if (series.AirDays.Count > 0)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</Airs_DayOfWeek>");
}
}
XmlSaverHelpers.AddCommonNodes(item, builder);

@ -149,7 +149,8 @@ namespace MediaBrowser.Providers.TV
if (!string.IsNullOrEmpty(path))
{
season.SetImage(ImageType.Thumb, await _providerManager.DownloadAndSaveImage(season, path, ThumbFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(season, path, FanArtResourcePool, ImageType.Thumb, null, cancellationToken)
.ConfigureAwait(false);
}
}
}

@ -234,7 +234,8 @@ namespace MediaBrowser.Providers.TV
var path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Logo, await _providerManager.DownloadAndSaveImage(item, path, LogoFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Logo, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -250,7 +251,8 @@ namespace MediaBrowser.Providers.TV
var path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Art, await _providerManager.DownloadAndSaveImage(item, path, ArtFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Art, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -263,7 +265,8 @@ namespace MediaBrowser.Providers.TV
var path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Thumb, await _providerManager.DownloadAndSaveImage(item, path, ThumbFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Thumb, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -274,7 +277,8 @@ namespace MediaBrowser.Providers.TV
var path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
item.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(item, path, BannerFile, ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Banner, null, cancellationToken)
.ConfigureAwait(false);
}
}
@ -292,7 +296,8 @@ namespace MediaBrowser.Providers.TV
if (!string.IsNullOrEmpty(path))
{
item.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(item, path, ("backdrop" + (numBackdrops > 0 ? numBackdrops.ToString(UsCulture) : "") + ".jpg"), ConfigurationManager.Configuration.SaveLocalMeta, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken)
.ConfigureAwait(false);
numBackdrops++;

@ -276,7 +276,10 @@ namespace MediaBrowser.Providers.TV
try
{
episode.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
var url = TVUtils.BannerUrl + p;
await _providerManager.SaveImage(episode, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
catch (HttpException)
{

@ -188,7 +188,12 @@ namespace MediaBrowser.Providers.TV
n = n.SelectSingleNode("./BannerPath");
if (n != null)
season.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
{
var url = TVUtils.BannerUrl + n.InnerText;
await _providerManager.SaveImage(season, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
}
}
@ -203,15 +208,10 @@ namespace MediaBrowser.Providers.TV
{
try
{
var bannerImagePath =
await _providerManager.DownloadAndSaveImage(season,
TVUtils.BannerUrl + n.InnerText,
"banner" +
Path.GetExtension(n.InnerText),
ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).
ConfigureAwait(false);
season.SetImage(ImageType.Banner, bannerImagePath);
var url = TVUtils.BannerUrl + n.InnerText;
await _providerManager.SaveImage(season, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken)
.ConfigureAwait(false);
}
catch (HttpException ex)
{
@ -235,7 +235,11 @@ namespace MediaBrowser.Providers.TV
n = n.SelectSingleNode("./BannerPath");
if (n != null)
{
season.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
var url = TVUtils.BannerUrl + n.InnerText;
await _providerManager.SaveImage(season, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, 0, cancellationToken)
.ConfigureAwait(false);
}
}
}

@ -215,13 +215,6 @@ namespace MediaBrowser.Providers.TV
await FetchSeriesData(series, seriesId, seriesDataPath, force, cancellationToken).ConfigureAwait(false);
}
BaseProviderInfo data;
if (!item.ProviderData.TryGetValue(Id, out data))
{
data = new BaseProviderInfo();
item.ProviderData[Id] = data;
}
SetLastRefreshed(item, DateTime.UtcNow);
return true;
}

@ -197,9 +197,10 @@ namespace MediaBrowser.Providers.TV
n = n.SelectSingleNode("./BannerPath");
if (n != null)
{
var path = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
var url = TVUtils.BannerUrl + n.InnerText;
series.SetImage(ImageType.Primary, path);
await _providerManager.SaveImage(series, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
}
}
@ -212,9 +213,10 @@ namespace MediaBrowser.Providers.TV
n = n.SelectSingleNode("./BannerPath");
if (n != null)
{
var bannerImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
var url = TVUtils.BannerUrl + n.InnerText;
series.SetImage(ImageType.Banner, bannerImagePath);
await _providerManager.SaveImage(series, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken)
.ConfigureAwait(false);
}
}
}
@ -232,8 +234,11 @@ namespace MediaBrowser.Providers.TV
if (p != null)
{
var bdName = "backdrop" + (bdNo > 0 ? bdNo.ToString(UsCulture) : "");
series.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
var url = TVUtils.BannerUrl + p.InnerText;
await _providerManager.SaveImage(series, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken)
.ConfigureAwait(false);
bdNo++;
}

@ -148,6 +148,7 @@
<Compile Include="Persistence\SqliteExtensions.cs" />
<Compile Include="Persistence\TypeMapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Providers\ImageSaver.cs" />
<Compile Include="Providers\ProviderManager.cs" />
<Compile Include="ScheduledTasks\ArtistValidationTask.cs" />
<Compile Include="ScheduledTasks\PeopleValidationTask.cs" />

@ -0,0 +1,255 @@
using System.Globalization;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Entities;
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Providers
{
/// <summary>
/// Class ImageSaver
/// </summary>
public class ImageSaver
{
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// The _config
/// </summary>
private readonly IServerConfigurationManager _config;
/// <summary>
/// The remote image cache
/// </summary>
private readonly FileSystemRepository _remoteImageCache;
/// <summary>
/// The _directory watchers
/// </summary>
private readonly IDirectoryWatchers _directoryWatchers;
/// <summary>
/// Initializes a new instance of the <see cref="ImageSaver"/> class.
/// </summary>
/// <param name="config">The config.</param>
/// <param name="directoryWatchers">The directory watchers.</param>
public ImageSaver(IServerConfigurationManager config, IDirectoryWatchers directoryWatchers)
{
_config = config;
_directoryWatchers = directoryWatchers;
_remoteImageCache = new FileSystemRepository(config.ApplicationPaths.DownloadedImagesDataPath);
}
/// <summary>
/// Saves the image.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="source">The source.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(mimeType))
{
throw new ArgumentNullException("mimeType");
}
var saveLocally = _config.Configuration.SaveLocalMeta;
if (item is IItemByName)
{
saveLocally = true;
}
else if (item is User)
{
saveLocally = true;
}
else if (item is Audio || item.Parent == null || string.IsNullOrEmpty(item.MetaLocation))
{
saveLocally = false;
}
if (type != ImageType.Primary)
{
if (item is Episode)
{
saveLocally = false;
}
}
if (item.LocationType != LocationType.FileSystem)
{
saveLocally = false;
}
var path = GetSavePath(item, type, imageIndex, mimeType, saveLocally);
var currentPath = GetCurrentImagePath(item, type, imageIndex);
try
{
_directoryWatchers.TemporarilyIgnore(path);
using (source)
{
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
{
await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
}
}
SetImagePath(item, type, imageIndex, path);
if (!string.IsNullOrEmpty(currentPath) && !string.Equals(path, currentPath, StringComparison.OrdinalIgnoreCase))
{
File.Delete(currentPath);
}
}
finally
{
_directoryWatchers.RemoveTempIgnore(path);
}
}
private string GetCurrentImagePath(BaseItem item, ImageType type, int? imageIndex)
{
switch (type)
{
case ImageType.Screenshot:
if (!imageIndex.HasValue)
{
throw new ArgumentNullException("imageIndex");
}
return item.ScreenshotImagePaths.Count > imageIndex.Value ? item.ScreenshotImagePaths[imageIndex.Value] : null;
case ImageType.Backdrop:
if (!imageIndex.HasValue)
{
throw new ArgumentNullException("imageIndex");
}
return item.BackdropImagePaths.Count > imageIndex.Value ? item.BackdropImagePaths[imageIndex.Value] : null;
default:
return item.GetImage(type);
}
}
private void SetImagePath(BaseItem item, ImageType type, int? imageIndex, string path)
{
switch (type)
{
case ImageType.Screenshot:
if (!imageIndex.HasValue)
{
throw new ArgumentNullException("imageIndex");
}
if (item.ScreenshotImagePaths.Count > imageIndex.Value)
{
item.ScreenshotImagePaths[imageIndex.Value] = path;
}
else
{
item.ScreenshotImagePaths.Add(path);
}
break;
case ImageType.Backdrop:
if (!imageIndex.HasValue)
{
throw new ArgumentNullException("imageIndex");
}
if (item.BackdropImagePaths.Count > imageIndex.Value)
{
item.BackdropImagePaths[imageIndex.Value] = path;
}
else
{
item.BackdropImagePaths.Add(path);
}
break;
default:
item.SetImage(type, path);
break;
}
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
/// <returns>System.String.</returns>
/// <exception cref="System.ArgumentNullException">
/// imageIndex
/// or
/// imageIndex
/// </exception>
private string GetSavePath(BaseItem item, ImageType type, int? imageIndex, string mimeType, bool saveLocally)
{
string filename;
switch (type)
{
case ImageType.Art:
filename = "clearart";
break;
case ImageType.Primary:
filename = item is Episode ? Path.GetFileNameWithoutExtension(item.Path) : "folder";
break;
case ImageType.Backdrop:
if (!imageIndex.HasValue)
{
throw new ArgumentNullException("imageIndex");
}
filename = imageIndex.Value == 0 ? "backdrop" : "backdrop" + imageIndex.Value.ToString(UsCulture);
break;
case ImageType.Screenshot:
if (!imageIndex.HasValue)
{
throw new ArgumentNullException("imageIndex");
}
filename = imageIndex.Value == 0 ? "screenshot" : "screenshot" + imageIndex.Value.ToString(UsCulture);
break;
default:
filename = type.ToString().ToLower();
break;
}
var extension = mimeType.Split('/').Last();
if (string.Equals(extension, "jpeg", StringComparison.OrdinalIgnoreCase))
{
extension = "jpg";
}
filename += "." + extension.ToLower();
var path = (saveLocally && !string.IsNullOrEmpty(item.MetaLocation)) ?
Path.Combine(item.MetaLocation, filename) :
_remoteImageCache.GetResourcePath(item.GetType().FullName + item.Id, filename);
var parentPath = Path.GetDirectoryName(path);
if (!Directory.Exists(parentPath))
{
Directory.CreateDirectory(parentPath);
}
return path;
}
}
}

@ -2,11 +2,14 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -22,11 +25,6 @@ namespace MediaBrowser.Server.Implementations.Providers
/// </summary>
public class ProviderManager : IProviderManager
{
/// <summary>
/// The remote image cache
/// </summary>
private readonly FileSystemRepository _remoteImageCache;
/// <summary>
/// The currently running metadata providers
/// </summary>
@ -74,7 +72,6 @@ namespace MediaBrowser.Server.Implementations.Providers
_httpClient = httpClient;
ConfigurationManager = configurationManager;
_directoryWatchers = directoryWatchers;
_remoteImageCache = new FileSystemRepository(configurationManager.ApplicationPaths.DownloadedImagesDataPath);
configurationManager.ConfigurationUpdated += configurationManager_ConfigurationUpdated;
}
@ -206,7 +203,7 @@ namespace MediaBrowser.Server.Implementations.Providers
try
{
var changed = await provider.FetchAsync(item, force, CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token).ConfigureAwait(false);
if (changed)
{
return provider.ItemUpdateType;
@ -315,90 +312,9 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public async Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, bool saveLocally, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
public Task<string> DownloadAndSaveImage(BaseItem item, string source, string targetName, bool saveLocally, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
if (string.IsNullOrEmpty(source))
{
throw new ArgumentNullException("source");
}
if (string.IsNullOrEmpty(targetName))
{
throw new ArgumentNullException("targetName");
}
if (resourcePool == null)
{
throw new ArgumentNullException("resourcePool");
}
var img = await _httpClient.Get(source, resourcePool, cancellationToken).ConfigureAwait(false);
//download and save locally
return await SaveImage(item, img, targetName, saveLocally, cancellationToken).ConfigureAwait(false);
}
public async Task<string> SaveImage(BaseItem item, Stream source, string targetName, bool saveLocally, CancellationToken cancellationToken)
{
//download and save locally
var localPath = GetSavePath(item, targetName, saveLocally);
if (saveLocally) // queue to media directories
{
await SaveToLibraryFilesystem(item, localPath, source, cancellationToken).ConfigureAwait(false);
}
else
{
// we can write directly here because it won't affect the watchers
try
{
using (var fs = new FileStream(localPath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
{
await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception e)
{
_logger.ErrorException("Error downloading and saving image " + localPath, e);
throw;
}
finally
{
source.Dispose();
}
}
return localPath;
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="targetFileName">Name of the target file.</param>
/// <param name="saveLocally">if set to <c>true</c> [save locally].</param>
/// <returns>System.String.</returns>
public string GetSavePath(BaseItem item, string targetFileName, bool saveLocally)
{
var path = (saveLocally && item.MetaLocation != null) ?
Path.Combine(item.MetaLocation, targetFileName) :
_remoteImageCache.GetResourcePath(item.GetType().FullName + item.Id.ToString(), targetFileName);
var parentPath = Path.GetDirectoryName(path);
if (!Directory.Exists(parentPath))
{
Directory.CreateDirectory(parentPath);
}
return path;
throw new HttpException(string.Empty) { IsTimedOut = true };
}
/// <summary>
@ -462,5 +378,45 @@ namespace MediaBrowser.Server.Implementations.Providers
_directoryWatchers.RemoveTempIgnore(path);
}
}
/// <summary>
/// Saves the image.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="url">The URL.</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task SaveImage(BaseItem item, string url, SemaphoreSlim resourcePool, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
var response = await _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
ResourcePool = resourcePool,
Url = url
}).ConfigureAwait(false);
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken)
.ConfigureAwait(false);
}
/// <summary>
/// Saves the image.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="source">The source.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
return new ImageSaver(ConfigurationManager, _directoryWatchers).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken);
}
}
}

Loading…
Cancel
Save