目前我正在研究.net MVC 5项目,我需要在硬盘上缓存一些数据。如何在服务器的硬盘上缓存数据和页面?
答案 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);