如何将asp.net mvc5缓存到硬盘?

时间:2016-07-24 10:06:21

标签: c# asp.net caching asp.net-mvc-5

目前我正在研究.net MVC 5项目,我需要在硬盘上缓存一些数据。如何在服务器的硬盘上缓存数据和页面?

2 个答案:

答案 0 :(得分:2)

您可以实现自定义OutputCacheProvider。

public class FileCacheProvider : OutputCacheProvider
{
    private string _cachePath;

    private string CachePath
    {
        get
        {
            if (!string.IsNullOrEmpty(_cachePath))
                return _cachePath;

            _cachePath = ConfigurationManager.AppSettings["OutputCachePath"];
            var context = HttpContext.Current;

            if (context != null)
            {
                _cachePath = context.Server.MapPath(_cachePath);
                if (!_cachePath.EndsWith("\\"))
                    _cachePath += "\\";
            }

            return _cachePath;
        }
    }

    public override object Add(string key, object entry, DateTime utcExpiry)
    {
        Debug.WriteLine("Cache.Add(" + key + ", " + entry + ", " + utcExpiry + ")");

        var path = GetPathFromKey(key);

        if (File.Exists(path))
            return entry;

        using (var file = File.OpenWrite(path))
        {
            var item = new CacheItem { Expires = utcExpiry, Item = entry };
            var formatter = new BinaryFormatter();
            formatter.Serialize(file, item);
        }

        return entry;
    }

    public override object Get(string key)
    {
        Debug.WriteLine("Cache.Get(" + key + ")");

        var path = GetPathFromKey(key);

        if (!File.Exists(path))
            return null;

        CacheItem item = null;

        using (var file = File.OpenRead(path))
        {
            var formatter = new BinaryFormatter();
            item = (CacheItem)formatter.Deserialize(file);
        }

        if (item == null || item.Expires <= DateTime.Now.ToUniversalTime())
        {
            Remove(key);
            return null;
        }

        return item.Item;
    }

    public override void Remove(string key)
    {
        Debug.WriteLine("Cache.Remove(" + key + ")");

        var path = GetPathFromKey(key);

        if (File.Exists(path))
            File.Delete(path);
    }

    public override void Set(string key, object entry, DateTime utcExpiry)
    {
        Debug.WriteLine("Cache.Set(" + key + ", " + entry + ", " + utcExpiry + ")");

        var item = new CacheItem { Expires = utcExpiry, Item = entry };
        var path = GetPathFromKey(key);

        using (var file = File.OpenWrite(path))
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(file, item);
        }
    }

    private string GetPathFromKey(string key)
    {
        return CachePath + MD5(key) + ".txt";
    }

    private string MD5(string s)
    {
        var provider = new MD5CryptoServiceProvider();
        var bytes = Encoding.UTF8.GetBytes(s);
        var builder = new StringBuilder();

        bytes = provider.ComputeHash(bytes);

        foreach (var b in bytes)
            builder.Append(b.ToString("x2").ToLower());

        return builder.ToString();
    }
}

并在web.config

中注册您的提供商
<appSettings>
  <add key="OutputCachePath" value="~/Cache/" />
</appSettings>

<caching>
  <outputCache defaultProvider="FileCache">
    <providers>
      <add name="FileCache" type="MyCacheProvider.FileCacheProvider, MyCacheProvider"/>
    </providers>
  </outputCache>
</caching>

答案 1 :(得分:0)

我确实得到了 Alexander 的答案,但我将在这里添加一些我在此过程中学到的东西。它正在使用:

使用 System.Security.Cryptography;
使用 System.IO;
使用 System.Runtime.Serialization.Formatters.Binary;
使用 System.Diagnostics;
使用 System.Web.Caching;

我需要添加这个类,它必须是可序列化的,否则会抛出错误:

[Serializable]
public class CacheItem
{
    public DateTime Expires { get; set; }
    public object Item { get; set; }
}

我不得不将 web.config 条目更改为此,因为答案似乎引用了不在代码中的命名空间。对此不太确定,而且我找不到有关此标签的任何文档:

<outputCache defaultProvider="FileCache">
    <providers>
      <add name="FileCache" type="FileCacheProvider"/>
    </providers>
  </outputCache>

这个可能有点明显,但是当您开始测试和使用它时,请确保过期时间是 UTC 时间:

DateTime expireTime = DateTime.UtcNow.AddHours(1);