diff --git a/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj b/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj
index 44d73c00b..0c659620c 100644
--- a/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj
+++ b/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj
@@ -55,6 +55,14 @@
+
+ {3c805e4c-d679-43f8-8c43-8909cdb4d4d7}
+ ImageProcessor.Web.AzureBlobCache
+
+
+ {d011a778-59c8-4bfa-a770-c350216bf161}
+ ImageProcessor.Web
+
{3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}
ImageProcessor
diff --git a/src/ImageProcessor.Playground/Program.cs b/src/ImageProcessor.Playground/Program.cs
index 937909347..e829732d8 100644
--- a/src/ImageProcessor.Playground/Program.cs
+++ b/src/ImageProcessor.Playground/Program.cs
@@ -24,6 +24,7 @@ namespace ImageProcessor.PlayGround
using ImageProcessor.Imaging.Filters.Photo;
using ImageProcessor.Imaging.Formats;
using ImageProcessor.Processors;
+ using ImageProcessor.Web.Caching;
///
/// The program.
@@ -38,6 +39,10 @@ namespace ImageProcessor.PlayGround
///
public static void Main(string[] args)
{
+ var x = typeof(AzureBlobCache);
+ Console.WriteLine(x.AssemblyQualifiedName);
+ Console.ReadLine();
+
string path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath;
// ReSharper disable once AssignNullToNotNullAttribute
diff --git a/src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs b/src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs
index 3820f421a..72c23c5ea 100644
--- a/src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs
+++ b/src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs
@@ -1,19 +1,17 @@
-namespace ImageProcessor.Web.AzureBlobCache
+namespace ImageProcessor.Web.Caching
{
using System;
using System.Collections.Generic;
- using System.Configuration;
using System.Globalization;
using System.IO;
using System.Linq;
+ using System.Net;
using System.Threading.Tasks;
using System.Web;
- using ImageProcessor.Web.Caching;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
- using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
@@ -36,7 +34,9 @@
private CloudBlobContainer cloudSourceBlobContainer;
- private string cachedContainerRoot;
+ private string cachedCDNRoot;
+
+ private string cachedRewritePath;
///
/// The physical cached path.
@@ -60,7 +60,7 @@
this.cloudCachedBlobContainer = this.cloudCachedBlobClient.GetContainerReference(this.Settings["CachedBlobContainer"]);
this.cloudSourceBlobContainer = this.cloudSourceBlobClient.GetContainerReference(this.Settings["SourceBlobContainer"]);
- this.cachedContainerRoot = this.Settings["CachedContainerRoot"];
+ this.cachedCDNRoot = this.Settings["CachedCDNRoot"];
}
public override int MaxDays
@@ -78,15 +78,36 @@
// Collision rate of about 1 in 10000 for the folder structure.
// That gives us massive scope to store millions of files.
string pathFromKey = string.Join("\\", cachedFileName.ToCharArray().Take(6));
- this.CachedPath = Path.Combine(this.cachedContainerRoot, pathFromKey, cachedFileName).Replace(@"\", "/");
+ this.CachedPath = Path.Combine(this.cloudCachedBlobContainer.Uri.ToString(), pathFromKey, cachedFileName).Replace(@"\", "/");
+ this.cachedRewritePath = Path.Combine(this.cachedCDNRoot, this.cloudCachedBlobContainer.Name, pathFromKey, cachedFileName).Replace(@"\", "/");
bool isUpdated = false;
CachedImage cachedImage = CacheIndexer.GetValue(this.CachedPath);
+ if (new Uri(this.CachedPath).IsFile)
+ {
+ FileInfo fileInfo = new FileInfo(this.CachedPath);
+
+ if (fileInfo.Exists)
+ {
+ // Pull the latest info.
+ fileInfo.Refresh();
+
+ cachedImage = new CachedImage
+ {
+ Key = Path.GetFileNameWithoutExtension(this.CachedPath),
+ Path = this.CachedPath,
+ CreationTimeUtc = fileInfo.CreationTimeUtc
+ };
+
+ CacheIndexer.Add(cachedImage);
+ }
+ }
+
if (cachedImage == null)
{
- ICloudBlob blockBlob =
- await this.cloudCachedBlobContainer.GetBlobReferenceFromServerAsync(this.RequestPath);
+ string blobPath = this.CachedPath.Substring(this.cloudCachedBlobContainer.Uri.ToString().Length + 1);
+ CloudBlockBlob blockBlob = this.cloudCachedBlobContainer.GetBlockBlobReference(blobPath);
if (await blockBlob.ExistsAsync())
{
@@ -106,21 +127,21 @@
CacheIndexer.Add(cachedImage);
}
}
+ }
- if (cachedImage == null)
+ if (cachedImage == null)
+ {
+ // Nothing in the cache so we should return true.
+ isUpdated = true;
+ }
+ else
+ {
+ // Check to see if the cached image is set to expire.
+ if (this.IsExpired(cachedImage.CreationTimeUtc))
{
- // Nothing in the cache so we should return true.
+ CacheIndexer.Remove(this.CachedPath);
isUpdated = true;
}
- else
- {
- // Check to see if the cached image is set to expire.
- if (this.IsExpired(cachedImage.CreationTimeUtc))
- {
- CacheIndexer.Remove(this.CachedPath);
- isUpdated = true;
- }
- }
}
return isUpdated;
@@ -128,7 +149,8 @@
public override async Task AddImageToCacheAsync(Stream stream)
{
- CloudBlockBlob blockBlob = this.cloudCachedBlobContainer.GetBlockBlobReference(this.CachedPath);
+ string blobPath = this.CachedPath.Substring(this.cloudCachedBlobContainer.Uri.ToString().Length + 1);
+ CloudBlockBlob blockBlob = this.cloudCachedBlobContainer.GetBlockBlobReference(blobPath);
await blockBlob.UploadFromStreamAsync(stream);
}
@@ -137,7 +159,7 @@
Uri uri = new Uri(this.CachedPath);
string path = uri.GetLeftPart(UriPartial.Path);
string directory = path.Substring(0, path.LastIndexOf('/'));
- string parent = directory.Substring(0, path.LastIndexOf('/'));
+ string parent = directory.Substring(this.cloudCachedBlobContainer.Uri.ToString().Length + 1, path.LastIndexOf('/'));
BlobContinuationToken continuationToken = null;
CloudBlobDirectory directoryBlob = this.cloudCachedBlobContainer.GetDirectoryReference(parent);
@@ -163,12 +185,10 @@
{
break;
}
- else
- {
- // Remove from the cache and delete each CachedImage.
- CacheIndexer.Remove(blob.Name);
- await blob.DeleteAsync();
- }
+
+ // Remove from the cache and delete each CachedImage.
+ CacheIndexer.Remove(blob.Name);
+ await blob.DeleteAsync();
}
}
@@ -180,8 +200,24 @@
{
if (new Uri(this.RequestPath).IsFile)
{
- ICloudBlob blockBlob = await this.cloudSourceBlobContainer
- .GetBlobReferenceFromServerAsync(this.RequestPath);
+ // Get the hash for the filestream. That way we can ensure that if the image is
+ // updated but has the same name we will know.
+ FileInfo imageFileInfo = new FileInfo(this.RequestPath);
+ if (imageFileInfo.Exists)
+ {
+ // Pull the latest info.
+ imageFileInfo.Refresh();
+
+ // Checking the stream itself is far too processor intensive so we make a best guess.
+ string creation = imageFileInfo.CreationTimeUtc.ToString(CultureInfo.InvariantCulture);
+ string length = imageFileInfo.Length.ToString(CultureInfo.InvariantCulture);
+ streamHash = string.Format("{0}{1}", creation, length);
+ }
+ }
+ else
+ {
+ string blobPath = this.CachedPath.Substring(this.cloudSourceBlobContainer.Uri.ToString().Length + 1);
+ CloudBlockBlob blockBlob = this.cloudSourceBlobContainer.GetBlockBlobReference(blobPath);
if (await blockBlob.ExistsAsync())
{
@@ -190,24 +226,11 @@
if (blockBlob.Properties.LastModified.HasValue)
{
- string creation = blockBlob.Properties.LastModified.Value.UtcDateTime.ToString(CultureInfo.InvariantCulture);
- string length = blockBlob.Properties.Length.ToString(CultureInfo.InvariantCulture);
- streamHash = string.Format("{0}{1}", creation, length);
- }
- }
- else
- {
- // Get the hash for the filestream. That way we can ensure that if the image is
- // updated but has the same name we will know.
- FileInfo imageFileInfo = new FileInfo(this.RequestPath);
- if (imageFileInfo.Exists)
- {
- // Pull the latest info.
- imageFileInfo.Refresh();
+ string creation = blockBlob.Properties
+ .LastModified.Value.UtcDateTime
+ .ToString(CultureInfo.InvariantCulture);
- // Checking the stream itself is far too processor intensive so we make a best guess.
- string creation = imageFileInfo.CreationTimeUtc.ToString(CultureInfo.InvariantCulture);
- string length = imageFileInfo.Length.ToString(CultureInfo.InvariantCulture);
+ string length = blockBlob.Properties.Length.ToString(CultureInfo.InvariantCulture);
streamHash = string.Format("{0}{1}", creation, length);
}
}
@@ -234,8 +257,16 @@
public override void RewritePath(HttpContext context)
{
- // The cached file is valid so just rewrite the path.
- context.RewritePath(this.CachedPath, false);
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.cachedRewritePath);
+ request.Method = "HEAD";
+
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+ {
+ HttpStatusCode responseCode = response.StatusCode;
+ context.Response.Redirect(
+ responseCode == HttpStatusCode.NotFound ? this.CachedPath : this.cachedRewritePath,
+ false);
+ }
}
}
}
diff --git a/src/ImageProcessor.Web.AzureBlobCache/ImageProcessor.Web.AzureBlobCache.csproj b/src/ImageProcessor.Web.AzureBlobCache/ImageProcessor.Web.AzureBlobCache.csproj
index f2b15b3ab..6e57a2a38 100644
--- a/src/ImageProcessor.Web.AzureBlobCache/ImageProcessor.Web.AzureBlobCache.csproj
+++ b/src/ImageProcessor.Web.AzureBlobCache/ImageProcessor.Web.AzureBlobCache.csproj
@@ -7,8 +7,8 @@
{3C805E4C-D679-43F8-8C43-8909CDB4D4D7}
Library
Properties
- ImageProcessor.Web.AzureBlobCache
- ImageProcessor.Web.AzureBlobCache
+ ImageProcessor.Web.Caching
+ ImageProcessor.Web.Caching.AzureBlobCache
v4.5
512
..\
diff --git a/src/ImageProcessor.Web.PostProcessor/PostProcessor.cs b/src/ImageProcessor.Web.PostProcessor/PostProcessor.cs
index 9d3a2be70..4144aea5b 100644
--- a/src/ImageProcessor.Web.PostProcessor/PostProcessor.cs
+++ b/src/ImageProcessor.Web.PostProcessor/PostProcessor.cs
@@ -34,6 +34,11 @@ namespace ImageProcessor.Web.PostProcessor
///
public static async Task PostProcessImageAsync(string sourceFile)
{
+ if (!new Uri(sourceFile).IsFile)
+ {
+ return;
+ }
+
string targetFile = Path.GetTempFileName();
PostProcessingResultEventArgs result = await RunProcess(sourceFile, targetFile);
diff --git a/src/ImageProcessor.Web/Caching/CacheIndexer.cs b/src/ImageProcessor.Web/Caching/CacheIndexer.cs
index 8a7786eb3..39654e83a 100644
--- a/src/ImageProcessor.Web/Caching/CacheIndexer.cs
+++ b/src/ImageProcessor.Web/Caching/CacheIndexer.cs
@@ -10,6 +10,7 @@
namespace ImageProcessor.Web.Caching
{
+ using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Caching;
@@ -64,11 +65,19 @@ namespace ImageProcessor.Web.Caching
///
public static CachedImage Add(CachedImage cachedImage)
{
- // Add the CachedImage.
- CacheItemPolicy policy = new CacheItemPolicy();
- policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List { cachedImage.Path }));
+ if (new Uri(cachedImage.Path).IsFile)
+ {
+ // Add the CachedImage.
+ CacheItemPolicy policy = new CacheItemPolicy();
+ policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List { cachedImage.Path }));
+
+ MemCache.AddItem(Path.GetFileNameWithoutExtension(cachedImage.Key), cachedImage, policy);
+ }
+ else
+ {
+ MemCache.AddItem(Path.GetFileNameWithoutExtension(cachedImage.Key), cachedImage);
+ }
- MemCache.AddItem(Path.GetFileNameWithoutExtension(cachedImage.Key), cachedImage, policy);
return cachedImage;
}
#endregion
diff --git a/src/ImageProcessor.Web/Configuration/ImageCacheSection.cs b/src/ImageProcessor.Web/Configuration/ImageCacheSection.cs
index 2aa05cc04..7847978f5 100644
--- a/src/ImageProcessor.Web/Configuration/ImageCacheSection.cs
+++ b/src/ImageProcessor.Web/Configuration/ImageCacheSection.cs
@@ -59,7 +59,7 @@ namespace ImageProcessor.Web.Configuration
/// The cache configuration section from the current application configuration.
public static ImageCacheSection GetConfiguration()
{
- ImageCacheSection imageCacheSection = ConfigurationManager.GetSection("imageProcessor/cache") as ImageCacheSection;
+ ImageCacheSection imageCacheSection = ConfigurationManager.GetSection("imageProcessor/caching") as ImageCacheSection;
if (imageCacheSection != null)
{
diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
index caf79a5b6..160d3d48e 100644
--- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
+++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
@@ -425,34 +425,6 @@ namespace ImageProcessor.Web.HttpModules
}
}
- // Image is from the cache so the mime-type will need to be set.
- // TODO: Is this bit needed? Is the static file handler doing stuff for the filecache
- // but not others.
- if (context.Items[CachedResponseTypeKey] == null)
- {
- string mimetype = ImageHelpers.GetMimeType(this.imageCache.CachedPath);
-
- if (!string.IsNullOrEmpty(mimetype))
- {
- context.Items[CachedResponseTypeKey] = mimetype;
- }
- }
-
- if (context.Items[CachedResponseFileDependency] == null)
- {
- if (isFileLocal)
- {
- // Some services might only provide filename so we can't monitor for the browser.
- context.Items[CachedResponseFileDependency] = Path.GetFileName(requestPath) == requestPath
- ? new List { this.imageCache.CachedPath }
- : new List { requestPath, this.imageCache.CachedPath };
- }
- else
- {
- context.Items[CachedResponseFileDependency] = new List { this.imageCache.CachedPath };
- }
- }
-
// The cached file is valid so just rewrite the path.
this.imageCache.RewritePath(context);
}
diff --git a/src/TestWebsites/MVC/Views/Home/Index.cshtml b/src/TestWebsites/MVC/Views/Home/Index.cshtml
index bceabd8ff..39dc3930e 100644
--- a/src/TestWebsites/MVC/Views/Home/Index.cshtml
+++ b/src/TestWebsites/MVC/Views/Home/Index.cshtml
@@ -7,24 +7,24 @@
Resized
-

-
Foreign language test.
+

+ @*
Foreign language test.
Strange name
-

+

*@
-
*@
-
+ @*
Reside Pad
@@ -199,9 +199,9 @@
-
+ *@
-
+@*
Color Profiles
@@ -223,4 +223,4 @@
-
\ No newline at end of file
+*@
\ No newline at end of file
diff --git a/src/TestWebsites/MVC/Web.config b/src/TestWebsites/MVC/Web.config
index eb09cc6d7..136c9c7fa 100644
--- a/src/TestWebsites/MVC/Web.config
+++ b/src/TestWebsites/MVC/Web.config
@@ -9,12 +9,12 @@
-
+
-
+