2015-06-17 1 views
0

Я написал пользовательскую реализацию VirtualPathProvider, которая позволяет мне извлекать изображения из хранилища Azure Blob. Поставщик делает свое дело, но звонит GetFile по каждому запросу, который не очень хорош для производительности.GetCacheDependency не вызывается в пользовательском VirtualPathProvider

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)); 
} 

Так как я знаю дату последнего изменения сгустка я думал, что это будет хорошая идея, чтобы добавить немного кэширования, но я не могу показаться, чтобы получить что-то работает.

Чтение вокруг него, кажется, мне нужно переопределить методы 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(); 
    } 
} 

I также имеют custo m CacheDependency осуществления.

public class BlobCacheDependency : CacheDependency 
{ 
    public BlobCacheDependency(DateTime lastModifiedUtc) 
    { 
     this.SetUtcLastModified(lastModifiedUtc); 
    } 
} 

К сожалению, ни один из этих методов никогда не вызывается при запросе изображений. Я не уверен, чего не хватает. Есть идеи?

ответ

1

Хорошо, так что ответ на этот вопрос заключается в том, чтобы установить кеш ответов в пределах метода Open() в моей реализации VirtualFile. Это позволяет браузеру кэшировать файл.

Это немного взломанный, но работает. В моем коде это выглядит так.

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

Смежные вопросы