diff --git a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs b/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs index be6b88744..c6300c64d 100644 --- a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs +++ b/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs @@ -49,14 +49,14 @@ namespace ImageProcessor.Web.Caching private const int MaxFilesCount = 100; /// - /// The absolute path to virtual cache path on the server. + /// The virtual cache path. /// - private static readonly string AbsoluteCachePath = HostingEnvironment.MapPath(ImageProcessorConfiguration.Instance.VirtualCachePath); + private static readonly string VirtualCachePath = ImageProcessorConfiguration.Instance.VirtualCachePath; /// - /// The request for the image. + /// The absolute path to virtual cache path on the server. /// - private readonly HttpRequest request; + private static readonly string AbsoluteCachePath = HostingEnvironment.MapPath(ImageProcessorConfiguration.Instance.VirtualCachePath); /// /// The request path for the image. @@ -72,15 +72,22 @@ namespace ImageProcessor.Web.Caching /// The image name /// private readonly string imageName; + + /// + /// The physical cached path. + /// + private string physicalCachedPath; + + /// + /// The virtual cached path. + /// + private string virtualCachedPath; #endregion #region Constructors /// /// Initializes a new instance of the class. /// - /// - /// The request for the image. - /// /// /// The request path for the image. /// @@ -90,53 +97,41 @@ namespace ImageProcessor.Web.Caching /// /// The image name. /// - public DiskCache(HttpRequest request, string requestPath, string fullPath, string imageName) + public DiskCache(string requestPath, string fullPath, string imageName) { - this.request = request; this.requestPath = requestPath; this.fullPath = fullPath; this.imageName = imageName; + + // Get the physical and virtual paths. + this.GetCachePaths(); } #endregion - #region Methods - #region Internal /// - /// Gets the full transformed cached path for the image. - /// The images are stored in paths that are based upon the SHA1 of their full request path - /// taking the individual characters of the hash to determine their location. - /// This allows us to store millions of images. + /// Gets the cached path. /// - /// The full cached path for the image. - internal Task GetCachePathAsync() + public string CachedPath { - return TaskHelpers.Run(this.GetCachePath); + get + { + return this.physicalCachedPath; + } } /// - /// Gets the virtual path to the cached processed image. + /// Gets the cached path. /// - /// - /// The path to the cached image. - /// - /// - /// The virtual path to the cached processed image. - /// - internal string GetVirtualCachedPath(string cachedPath) + public string VirtualCachedPath { - string applicationPath = this.request.PhysicalApplicationPath; - string virtualDir = this.request.ApplicationPath; - virtualDir = virtualDir == "/" ? virtualDir : (virtualDir + "/"); - - if (applicationPath != null) + get { - return cachedPath.Replace(applicationPath, virtualDir).Replace(@"\", "/"); + return this.virtualCachedPath; } - - throw new InvalidOperationException( - "We can only map an absolute back to a relative path if the application path is available."); } + #region Methods + #region Internal /// /// Adds an image to the cache. /// @@ -256,15 +251,13 @@ namespace ImageProcessor.Web.Caching } /// - /// Gets the full transformed cached path for the image. + /// Gets the full transformed cached paths for the image. /// The images are stored in paths that are based upon the SHA1 of their full request path /// taking the individual characters of the hash to determine their location. /// This allows us to store millions of images. /// - /// The full cached path for the image. - private string GetCachePath() + private void GetCachePaths() { - string cachedPath = string.Empty; string streamHash = string.Empty; if (AbsoluteCachePath != null) @@ -302,16 +295,16 @@ namespace ImageProcessor.Web.Caching // Collision rate of about 1 in 10000 for the folder structure. string pathFromKey = string.Join("\\", encryptedName.ToCharArray().Take(6)); + string virtualPathFromKey = pathFromKey.Replace(@"\", "/"); string cachedFileName = string.Format( "{0}.{1}", encryptedName, !string.IsNullOrWhiteSpace(parsedExtension) ? parsedExtension.Replace(".", string.Empty) : fallbackExtension); - cachedPath = Path.Combine(AbsoluteCachePath, pathFromKey, cachedFileName); + this.physicalCachedPath = Path.Combine(AbsoluteCachePath, pathFromKey, cachedFileName); + this.virtualCachedPath = Path.Combine(VirtualCachePath, virtualPathFromKey, cachedFileName).Replace(@"\", "/"); } - - return cachedPath; } /// diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs index db378fae4..0f4db86f3 100644 --- a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs @@ -13,7 +13,6 @@ namespace ImageProcessor.Web.HttpModules #region Using using System; using System.Collections.Concurrent; - using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -157,12 +156,11 @@ namespace ImageProcessor.Web.HttpModules /// The id representing the . /// /// - /// The for the given id. + /// The for the given id. /// private static SemaphoreSlim GetSemaphoreSlim(string id) { - SemaphoreSlim semaphore = SemaphoreSlims.GetOrAdd(id, new SemaphoreSlim(1, 1)); - return semaphore; + return SemaphoreSlims.GetOrAdd(id, new SemaphoreSlim(1, 1)); } /// @@ -179,12 +177,6 @@ namespace ImageProcessor.Web.HttpModules if (disposing) { // Dispose of any managed resources here. - foreach (KeyValuePair semaphore in SemaphoreSlims) - { - semaphore.Value.Dispose(); - } - - SemaphoreSlims.Clear(); } // Call the appropriate methods to clean up @@ -346,15 +338,15 @@ namespace ImageProcessor.Web.HttpModules } // Create a new cache to help process and cache the request. - DiskCache cache = new DiskCache(request, requestPath, fullPath, imageName); - string cachedPath = await cache.GetCachePathAsync(); + DiskCache cache = new DiskCache(requestPath, fullPath, imageName); + string cachedPath = cache.CachedPath; // Since we are now rewriting the path we need to check again that the current user has access // to the rewritten path. // Get the user for the current request // If the user is anonymous or authentication doesn't work for this suffix avoid a NullReferenceException // in the UrlAuthorizationModule by creating a generic identity. - string virtualCachedPath = cache.GetVirtualCachedPath(cachedPath); + string virtualCachedPath = cache.VirtualCachedPath; IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]); @@ -362,7 +354,7 @@ namespace ImageProcessor.Web.HttpModules PermissionSet permission = new PermissionSet(PermissionState.None); permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted)); bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet); - + bool isAllowed = true; // Run the rewritten path past the authorization system again. @@ -385,17 +377,19 @@ namespace ImageProcessor.Web.HttpModules { if (isRemote) { - Uri uri = new Uri(requestPath + "?" + urlParameters); - - RemoteFile remoteFile = new RemoteFile(uri, false); - - // Prevent response blocking. - WebResponse webResponse = await remoteFile.GetWebResponseAsync().ConfigureAwait(false); - SemaphoreSlim semaphore = GetSemaphoreSlim(cachedPath); +#if NET45 && !__MonoCS__ + await semaphore.WaitAsync(); +#else + semaphore.Wait(); +#endif try { - semaphore.Wait(); + Uri uri = new Uri(requestPath + "?" + urlParameters); + RemoteFile remoteFile = new RemoteFile(uri, false); + + // Prevent response blocking. + WebResponse webResponse = await remoteFile.GetWebResponseAsync().ConfigureAwait(false); using (MemoryStream memoryStream = new MemoryStream()) { @@ -435,19 +429,22 @@ namespace ImageProcessor.Web.HttpModules } else { - // Check to see if the file exists. - // ReSharper disable once AssignNullToNotNullAttribute - FileInfo fileInfo = new FileInfo(requestPath); - - if (!fileInfo.Exists) - { - throw new HttpException(404, "No image exists at " + fullPath); - } - SemaphoreSlim semaphore = GetSemaphoreSlim(cachedPath); +#if NET45 && !__MonoCS__ + await semaphore.WaitAsync(); +#else + semaphore.Wait(); +#endif try { - semaphore.Wait(); + // Check to see if the file exists. + // ReSharper disable once AssignNullToNotNullAttribute + FileInfo fileInfo = new FileInfo(requestPath); + + if (!fileInfo.Exists) + { + throw new HttpException(404, "No image exists at " + fullPath); + } // Process the Image imageFactory.Load(requestPath) diff --git a/src/ImageProcessor/Imaging/Formats/GifFormat.cs b/src/ImageProcessor/Imaging/Formats/GifFormat.cs index 83904225b..dffccb99b 100644 --- a/src/ImageProcessor/Imaging/Formats/GifFormat.cs +++ b/src/ImageProcessor/Imaging/Formats/GifFormat.cs @@ -86,7 +86,7 @@ namespace ImageProcessor.Imaging.Formats foreach (GifFrame frame in info.GifFrames) { factory.Image = frame.Image; - frame.Image = quantizer.Quantize(processor.Invoke(factory)); + frame.Image = quantizer.Quantize(processor.Invoke(factory)); encoder.AddFrame(frame); } } diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Web.config b/src/TestWebsites/NET45/Test_Website_NET45/Web.config index 67e336777..8cfc303d3 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Web.config +++ b/src/TestWebsites/NET45/Test_Website_NET45/Web.config @@ -6,17 +6,17 @@ - + - +