covers are re-downloaded if remote size is different than

local size.
This commit is contained in:
kay.one 2013-05-28 21:10:23 -07:00
parent 1d007be8fd
commit e2d17ac109
10 changed files with 154 additions and 8 deletions

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net; using System.Net;
@ -12,6 +13,8 @@ namespace NzbDrone.Common
string DownloadString(string address); string DownloadString(string address);
string DownloadString(string address, string username, string password); string DownloadString(string address, string username, string password);
string DownloadString(string address, ICredentials identity); string DownloadString(string address, ICredentials identity);
Dictionary<string, string> DownloadHeader(string url);
Stream DownloadStream(string url, NetworkCredential credential = null); Stream DownloadStream(string url, NetworkCredential credential = null);
void DownloadFile(string url, string fileName); void DownloadFile(string url, string fileName);
string PostCommand(string address, string username, string password, string command); string PostCommand(string address, string username, string password, string command);
@ -19,6 +22,9 @@ namespace NzbDrone.Common
public class HttpProvider : IHttpProvider public class HttpProvider : IHttpProvider
{ {
public const string ContentLenghtHeader = "Content-Length";
private readonly IEnvironmentProvider _environmentProvider; private readonly IEnvironmentProvider _environmentProvider;
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly string _userAgent; private readonly string _userAgent;
@ -54,6 +60,22 @@ namespace NzbDrone.Common
} }
} }
public Dictionary<string, string> DownloadHeader(string url)
{
var headers = new Dictionary<string, string>();
var request = WebRequest.Create(url);
request.Method = "HEAD";
var response = request.GetResponse();
foreach (var key in headers.Keys)
{
headers.Add(key, response.Headers[key]);
}
return headers;
}
public Stream DownloadStream(string url, NetworkCredential credential = null) public Stream DownloadStream(string url, NetworkCredential credential = null)
{ {
var request = (HttpWebRequest)WebRequest.Create(url); var request = (HttpWebRequest)WebRequest.Create(url);
@ -70,7 +92,7 @@ namespace NzbDrone.Common
try try
{ {
var fileInfo = new FileInfo(fileName); var fileInfo = new FileInfo(fileName);
if (!fileInfo.Directory.Exists) if (fileInfo.Directory != null && !fileInfo.Directory.Exists)
{ {
fileInfo.Directory.Create(); fileInfo.Directory.Create();
} }

View File

@ -18,7 +18,7 @@ namespace NzbDrone.Common
string[] GetDirectories(string path); string[] GetDirectories(string path);
string[] GetFiles(string path, SearchOption searchOption); string[] GetFiles(string path, SearchOption searchOption);
long GetDirectorySize(string path); long GetDirectorySize(string path);
long GetSize(string path); long GetFileSize(string path);
String CreateFolder(string path); String CreateFolder(string path);
void CopyDirectory(string source, string target); void CopyDirectory(string source, string target);
void MoveDirectory(string source, string destination); void MoveDirectory(string source, string destination);
@ -131,7 +131,7 @@ namespace NzbDrone.Common
return GetFiles(path, SearchOption.AllDirectories).Sum(e => new FileInfo(e).Length); return GetFiles(path, SearchOption.AllDirectories).Sum(e => new FileInfo(e).Length);
} }
public virtual long GetSize(string path) public virtual long GetFileSize(string path)
{ {
Ensure.That(() => path).IsValidPath(); Ensure.That(() => path).IsValidPath();

View File

@ -0,0 +1,72 @@
using System.Collections.Generic;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.MediaCoverTests
{
[TestFixture]
public class CoverAlreadyExistsSpecificationFixture : CoreTest<CoverAlreadyExistsSpecification>
{
private Dictionary<string, string> _headers;
[SetUp]
public void Setup()
{
_headers = new Dictionary<string, string>();
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetFileSize(It.IsAny<string>())).Returns(100);
Mocker.GetMock<IHttpProvider>().Setup(c => c.DownloadHeader(It.IsAny<string>())).Returns(_headers);
}
private void GivenFileExistsOnDisk()
{
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileExists(It.IsAny<string>())).Returns(true);
}
private void GivenExistingFileSize(long bytes)
{
GivenFileExistsOnDisk();
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetFileSize(It.IsAny<string>())).Returns(bytes);
}
[Test]
public void should_return_false_if_file_not_exists()
{
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse();
}
[Test]
public void should_return_false_if_file_exists_but_diffrent_size()
{
GivenExistingFileSize(100);
_headers.Add(HttpProvider.ContentLenghtHeader, "200");
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse();
}
[Test]
public void should_return_ture_if_file_exists_and_same_size()
{
GivenExistingFileSize(100);
_headers.Add(HttpProvider.ContentLenghtHeader, "100");
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue();
}
[Test]
public void should_return_true_if_there_is_no_size_header_and_file_exist()
{
GivenExistingFileSize(100);
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue();
}
}
}

View File

@ -142,6 +142,7 @@
<Compile Include="JobTests\JobRepositoryFixture.cs" /> <Compile Include="JobTests\JobRepositoryFixture.cs" />
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />
<Compile Include="JobTests\TestJobs.cs" /> <Compile Include="JobTests\TestJobs.cs" />
<Compile Include="MediaCoverTests\CoverExistsSpecificationFixture.cs" />
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" /> <Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
<Compile Include="MediaFileTests\MediaFileTableCleanupServiceFixture.cs" /> <Compile Include="MediaFileTests\MediaFileTableCleanupServiceFixture.cs" />
<Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" /> <Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" />

View File

@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
_fileSize = size; _fileSize = size;
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(d => d.GetSize(It.IsAny<String>())) .Setup(d => d.GetFileSize(It.IsAny<String>()))
.Returns(size); .Returns(size);
} }

View File

@ -0,0 +1,47 @@
using NzbDrone.Common;
namespace NzbDrone.Core.MediaCover
{
public interface ICoverExistsSpecification
{
bool AlreadyExists(string url, string paht);
}
public class CoverAlreadyExistsSpecification : ICoverExistsSpecification
{
private readonly IDiskProvider _diskProvider;
private readonly IHttpProvider _httpProvider;
public CoverAlreadyExistsSpecification(IDiskProvider diskProvider, IHttpProvider httpProvider)
{
_diskProvider = diskProvider;
_httpProvider = httpProvider;
}
public bool AlreadyExists(string url, string path)
{
if (!_diskProvider.FileExists(path))
{
return false;
}
var headers = _httpProvider.DownloadHeader(url);
string sizeString = null;
if (headers.TryGetValue(HttpProvider.ContentLenghtHeader, out sizeString))
{
int size;
int.TryParse(sizeString, out size);
var fileSize = _diskProvider.GetFileSize(path);
if (fileSize != size)
{
return false;
}
}
return true;
}
}
}

View File

@ -14,14 +14,17 @@ namespace NzbDrone.Core.MediaCover
{ {
private readonly IHttpProvider _httpProvider; private readonly IHttpProvider _httpProvider;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly ICoverExistsSpecification _coverExistsSpecification;
private readonly Logger _logger; private readonly Logger _logger;
private readonly string _coverRootFolder; private readonly string _coverRootFolder;
public MediaCoverService(IHttpProvider httpProvider, IDiskProvider diskProvider, IEnvironmentProvider environmentProvider, Logger logger) public MediaCoverService(IHttpProvider httpProvider, IDiskProvider diskProvider, IEnvironmentProvider environmentProvider,
ICoverExistsSpecification coverExistsSpecification, Logger logger)
{ {
_httpProvider = httpProvider; _httpProvider = httpProvider;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_coverExistsSpecification = coverExistsSpecification;
_logger = logger; _logger = logger;
_coverRootFolder = environmentProvider.GetMediaCoverPath(); _coverRootFolder = environmentProvider.GetMediaCoverPath();
@ -37,7 +40,7 @@ namespace NzbDrone.Core.MediaCover
foreach (var cover in series.Images) foreach (var cover in series.Images)
{ {
var fileName = GetCoverPath(series.Id, cover.CoverType); var fileName = GetCoverPath(series.Id, cover.CoverType);
if (!_diskProvider.FileExists(fileName)) if (!_coverExistsSpecification.AlreadyExists(cover.Url, fileName))
{ {
DownloadCover(series, cover); DownloadCover(series, cover);
} }

View File

@ -86,7 +86,7 @@ namespace NzbDrone.Core.MediaFiles
return null; return null;
} }
var size = _diskProvider.GetSize(filePath); var size = _diskProvider.GetFileSize(filePath);
if (series.SeriesType == SeriesTypes.Daily || parsedEpisode.SeasonNumber > 0) if (series.SeriesType == SeriesTypes.Daily || parsedEpisode.SeasonNumber > 0)
{ {

View File

@ -87,7 +87,7 @@ namespace NzbDrone.Core.MetadataSource
var extension = Path.GetExtension(posterUrl); var extension = Path.GetExtension(posterUrl);
var withoutExtension = posterUrl.Substring(0, posterUrl.Length - extension.Length); var withoutExtension = posterUrl.Substring(0, posterUrl.Length - extension.Length);
return withoutExtension + "-138" + extension; return withoutExtension + "-300" + extension;
} }
private static SeriesStatusType GetSeriesStatus(string status) private static SeriesStatusType GetSeriesStatus(string status)

View File

@ -249,6 +249,7 @@
<Compile Include="Indexers\RssSyncCommand.cs" /> <Compile Include="Indexers\RssSyncCommand.cs" />
<Compile Include="Jobs\TaskManager.cs" /> <Compile Include="Jobs\TaskManager.cs" />
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" /> <Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
<Compile Include="MediaCover\CoverAlreadyExistsSpecification.cs" />
<Compile Include="MediaFiles\Commands\CleanMediaFileDb.cs" /> <Compile Include="MediaFiles\Commands\CleanMediaFileDb.cs" />
<Compile Include="MediaFiles\Commands\CleanUpRecycleBinCommand.cs" /> <Compile Include="MediaFiles\Commands\CleanUpRecycleBinCommand.cs" />
<Compile Include="MediaFiles\Commands\DownloadedEpisodesScanCommand.cs" /> <Compile Include="MediaFiles\Commands\DownloadedEpisodesScanCommand.cs" />