自定义 VirtualPathProvider 中未调用 GetCacheDependency
GetCacheDependency not called in custom VirtualPathProvider
我编写了 VirtualPathProvider 的自定义实现,它允许我从 Azure Blob 存储中提取图像。提供者会做它的事情,但会根据每个请求调用 GetFile
,这对性能来说不是很好。
GetFile
public override VirtualFile GetFile(string virtualPath)
{
string path = this.FormatVirtualPath(virtualPath);
if (!path.StartsWith(this.pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
return base.GetFile(virtualPath);
}
string fileSystemPath = this.RemovePathPrefix(path);
return new FileSystemVirtualFile(
virtualPath,
() =>
this.fileSystem.Value.OpenFile(fileSystemPath));
}
因为我知道 blob 的最后修改日期,所以我认为添加一些缓存是个好主意,但我似乎无法正常工作。
阅读它似乎我需要覆盖方法 GetCacheDependency
和 GetFileHash
我已经这样做了,如下所示:
GetCacheDependency
public override CacheDependency GetCacheDependency(string virtualPath,
IEnumerable virtualPathDependencies,
DateTime utcStart)
{
string path = this.FormatVirtualPath(virtualPath);
if (!path.StartsWith(this.pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
return base.GetCacheDependency(virtualPath,
virtualPathDependencies,
utcStart);
}
return new BlobCacheDependency(
this.fileSystem
.Value.GetLastModified(path)
.DateTime.ToUniversalTime());
}
GetFileHash
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
{
string path = this.FormatVirtualPath(virtualPath);
if (!path.StartsWith(this.pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
byte[] bytes = Encoding.Unicode.GetBytes(virtualPath.ToCharArray());
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
byte[] hash = md5.ComputeHash(bytes);
// Concatenate the hash bytes into one long String.
return hash.Aggregate(
new StringBuilder(32),
(sb, b) => sb.Append(b.ToString("X2",
CultureInfo.InvariantCulture)))
.ToString().ToLowerInvariant();
}
}
我还有一个自定义 CacheDependency
实现。
public class BlobCacheDependency : CacheDependency
{
public BlobCacheDependency(DateTime lastModifiedUtc)
{
this.SetUtcLastModified(lastModifiedUtc);
}
}
不幸的是,在请求图像时,这些其他方法都没有被调用。我不确定缺少什么。有什么想法吗?
好的,答案是在我的 VirtualFile
实现中的 Open()
方法中设置响应缓存。这允许浏览器缓存文件。
它有点老套,但很管用。在我的代码中,它现在看起来像这样。
public override Stream Open()
{
// Set the response headers here. It's a bit hacky.
HttpCachePolicy cache = HttpContext.Current.Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.VaryByHeaders["Accept-Encoding"] = true;
IFileSystem azureBlobFileSystem = FileSystemProviderManager.Current.GetUnderlyingFileSystemProvider("media");
int maxDays = ((AzureBlobFileSystem)azureBlobFileSystem).FileSystem.MaxDays;
cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(maxDays));
cache.SetMaxAge(new TimeSpan(maxDays, 0, 0, 0));
cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
return this.stream();
}
见
http://forums.asp.net/t/1745003.aspx?VirtualPathProvider+files+do+not+have+cache+control+headers
我编写了 VirtualPathProvider 的自定义实现,它允许我从 Azure Blob 存储中提取图像。提供者会做它的事情,但会根据每个请求调用 GetFile
,这对性能来说不是很好。
GetFile
public override VirtualFile GetFile(string virtualPath)
{
string path = this.FormatVirtualPath(virtualPath);
if (!path.StartsWith(this.pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
return base.GetFile(virtualPath);
}
string fileSystemPath = this.RemovePathPrefix(path);
return new FileSystemVirtualFile(
virtualPath,
() =>
this.fileSystem.Value.OpenFile(fileSystemPath));
}
因为我知道 blob 的最后修改日期,所以我认为添加一些缓存是个好主意,但我似乎无法正常工作。
阅读它似乎我需要覆盖方法 GetCacheDependency
和 GetFileHash
我已经这样做了,如下所示:
GetCacheDependency
public override CacheDependency GetCacheDependency(string virtualPath,
IEnumerable virtualPathDependencies,
DateTime utcStart)
{
string path = this.FormatVirtualPath(virtualPath);
if (!path.StartsWith(this.pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
return base.GetCacheDependency(virtualPath,
virtualPathDependencies,
utcStart);
}
return new BlobCacheDependency(
this.fileSystem
.Value.GetLastModified(path)
.DateTime.ToUniversalTime());
}
GetFileHash
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
{
string path = this.FormatVirtualPath(virtualPath);
if (!path.StartsWith(this.pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
byte[] bytes = Encoding.Unicode.GetBytes(virtualPath.ToCharArray());
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
byte[] hash = md5.ComputeHash(bytes);
// Concatenate the hash bytes into one long String.
return hash.Aggregate(
new StringBuilder(32),
(sb, b) => sb.Append(b.ToString("X2",
CultureInfo.InvariantCulture)))
.ToString().ToLowerInvariant();
}
}
我还有一个自定义 CacheDependency
实现。
public class BlobCacheDependency : CacheDependency
{
public BlobCacheDependency(DateTime lastModifiedUtc)
{
this.SetUtcLastModified(lastModifiedUtc);
}
}
不幸的是,在请求图像时,这些其他方法都没有被调用。我不确定缺少什么。有什么想法吗?
好的,答案是在我的 VirtualFile
实现中的 Open()
方法中设置响应缓存。这允许浏览器缓存文件。
它有点老套,但很管用。在我的代码中,它现在看起来像这样。
public override Stream Open()
{
// Set the response headers here. It's a bit hacky.
HttpCachePolicy cache = HttpContext.Current.Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.VaryByHeaders["Accept-Encoding"] = true;
IFileSystem azureBlobFileSystem = FileSystemProviderManager.Current.GetUnderlyingFileSystemProvider("media");
int maxDays = ((AzureBlobFileSystem)azureBlobFileSystem).FileSystem.MaxDays;
cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(maxDays));
cache.SetMaxAge(new TimeSpan(maxDays, 0, 0, 0));
cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
return this.stream();
}
见
http://forums.asp.net/t/1745003.aspx?VirtualPathProvider+files+do+not+have+cache+control+headers