Remove Image from Image Processor Cache

Vote:
 

I have a project where we want update images and pdfs with a new file with the same name. There are several parts to this process:

  1. When adding the image to the CMS, we get the option to replace. This works.
  2. On the DXC, we need to cache bust the CDN. We are doing this by adding a hash based on publish date to all media items as a query string. This also works.
  3. The part where we run into trouble is the server cache:

When we replace the media item in the CMS, we dont see the new item until we restart the app pool. I tried removing the item from the content cache:

contentCacheRemover.Remove(content.ContentLink);

This has no effect. Im thinking that I need to remove the image from the ImageProcessor cache, but I cant figure out how to do that. Is it possible to remove a single item from the ImageProcessor cache?

#279806
May 04, 2022 13:44
Vote:
 

Hi Ethan,

I've done something similar before and this would depend on whether you're using Azure or not. If you are, then you can do something like this:

public class AzureBlobCacheDeleter
{
	private static CloudBlobContainer _container;
	private readonly IContentLoader _contentLoader;

	private const string prefix = "3p!_";

	private readonly ILogger _logger = LogManager.GetLogger(typeof(AzureBlobCacheDeleter));

	public AzureBlobCacheDeleter(IContentLoader contentLoader)
	{
		TrySetCloudBlobContainer();
		_contentLoader = contentLoader;
	}

	public void TrySetCloudBlobContainer()
	{
		try
		{
			var provider = EPiServerFrameworkSection.Instance.Blob.Providers[EPiServerFrameworkSection.Instance.Blob.DefaultProvider];

			string connectionString = ConfigurationManager.ConnectionStrings[provider.Parameters[AzureBlobProvider.ConnectionStringNameKey]].ConnectionString;

			string containerName = provider.Parameters[AzureBlobProvider.ContainerKey];

			_container = CloudStorageAccount.Parse(connectionString).CreateCloudBlobClient().GetContainerReference(containerName);
		}
		catch (Exception ex)
		{
			_logger.Error("Failed to resolve an Azure blob service container.", ex);
		}
	}

	public bool TryDeleteCachedImages(ContentReference imageLink)
	{
		if (ContentReference.IsNullOrEmpty(imageLink))
		{
			return false;
		}

		if (_container == null)
		{
			// This can only be run on environment with a configured Azure blob service container.
			return false;
		}

		if (!_contentLoader.TryGet<MediaData>(imageLink, out var mediaData))
		{
			return false;
		}

		var binaryDataContainer = mediaData.BinaryDataContainer;

		var segment = binaryDataContainer.Segments[1];

		if (string.IsNullOrEmpty(segment))
		{
			return false;
		}

		var results = _container.ListBlobs(segment, true, BlobListingDetails.None);

		foreach (var blob in results.OfType<CloudBlockBlob>())
		{
			if (!blob.Name.Contains(prefix))
			{
				continue;
			}


			CacheIndexer.Remove(blob.Name);
			blob.Delete();
		}

		return true;
	}
}

This is essentially based on looking into how the AzureBlobCache works (ImageProcessor.Web.Episerver.Azure). If you're using the FileBlobCache (ImageProcessor.Web.Episerver) I'd imagine you'd do something very similar, but I don't have a code snippet for that. 😊 I'd probably start by looking at the code (https://github.com/vnbaaij/ImageProcessor.Web.Episerver/blob/master/src/ImageProcessor.Web.Episerver/FileBlobCache.cs) especially the TrimCacheAsync method.

Good luck!

#280050
Edited, May 09, 2022 15:34
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.