缓存存储在文件中,根据过期时间过期,也可以手动删除。IIS回收进程时缓存不丢失。

代码:

文件缓存_html文件缓存_键值对_02

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace Common.Utils
{
/// <summary>
/// 缓存工具类
/// </summary>
public static class CacheUtil
{
#region 变量
/// <summary>
/// 缓存路径
/// </summary>
private static string folderPath = Application.StartupPath + "\\cache";
/// <summary>
/// 锁
/// </summary>
private static object _lock = new object();
private static BinaryFormatter formatter = new BinaryFormatter();
#endregion

#region 构造函数
static CacheUtil()
{
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
}
#endregion

#region SetValue 保存键值对
/// <summary>
/// 保存键值对
/// </summary>
public static void SetValue(string key, object value, int expirationMinutes = 0)
{
CacheData data = new CacheData(key, value);
data.updateTime = DateTime.Now;
data.expirationMinutes = expirationMinutes;

string keyMd5 = GetMD5(key);
string path = folderPath + "\\" + keyMd5 + ".txt";
lock (_lock)
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fs.SetLength(0);
formatter.Serialize(fs, data);
fs.Close();
}
}
}
#endregion

#region GetValue 获取键值对
/// <summary>
/// 获取键值对
/// </summary>
public static object GetValue(string key)
{
string keyMd5 = GetMD5(key);
string path = folderPath + "\\" + keyMd5 + ".txt";
if (File.Exists(path))
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
CacheData data = (CacheData)formatter.Deserialize(fs);
fs.Close();
if (data.expirationMinutes > 0 && DateTime.Now.Subtract(data.updateTime).TotalMinutes > data.expirationMinutes)
{
File.Delete(path);
return null;
}
return data.value;
}
}
return null;
}
#endregion

#region Delete 删除
/// <summary>
/// 删除
/// </summary>
public static void Delete(string key)
{
string keyMd5 = GetMD5(key);
string path = folderPath + "\\" + keyMd5 + ".txt";
if (File.Exists(path))
{
lock (_lock)
{
File.Delete(path);
}
}
}
#endregion

#region DeleteAll 全部删除
/// <summary>
/// 全部删除
/// </summary>
public static void DeleteAll()
{
string[] files = Directory.GetFiles(folderPath);
foreach (string file in files)
{
File.Delete(file);
}
}
#endregion

#region 计算MD5值
/// <summary>
/// 计算MD5值
/// </summary>
private static string GetMD5(string value)
{
string base64 = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(value)).Replace("/", "-");
if (base64.Length > 200)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] bArr = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value));
StringBuilder sb = new StringBuilder();
foreach (byte b in bArr)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
return base64;
}
#endregion
}

#region CacheData 缓存数据
/// <summary>
/// 缓存数据
/// </summary>
[Serializable]
public class CacheData
{
/// <summary>
/// 键
/// </summary>
public string key { get; set; }
/// <summary>
/// 值
/// </summary>
public object value { get; set; }
/// <summary>
/// 缓存更新时间
/// </summary>
public DateTime updateTime { get; set; }
/// <summary>
/// 过期时间(分钟),0表示永不过期
/// </summary>
public int expirationMinutes { get; set; }

public CacheData(string key, object value)
{
this.key = key;
this.value = value;
}
}
#endregion

}

View Code

带文件依赖版:

文件缓存_html文件缓存_键值对_02

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using System.Web;

namespace Common.Utils
{
/// <summary>
/// 缓存工具类
/// 缓存数据存储在文件中
/// </summary>
public static class CacheUtil
{
#region 变量
/// <summary>
/// 锁
/// </summary>
private static object _lock = new object();
private static BinaryFormatter formatter = new BinaryFormatter();
#endregion

#region SetValue 保存键值对
/// <summary>
/// 保存键值对
/// </summary>
public static void SetValue(HttpServerUtilityBase server, string key, object value, string dependentFilePath, int expirationMinutes = 0)
{
CacheData data = new CacheData(key, value);
data.updateTime = DateTime.Now;
data.expirationMinutes = expirationMinutes;
data.dependentFilePath = dependentFilePath;

string folderPath = server.MapPath("~/bin/cache");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}

string keyMd5 = GetMD5(key);
string path = folderPath + "\\" + keyMd5 + ".txt";
lock (_lock)
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fs.SetLength(0);
formatter.Serialize(fs, data);
fs.Close();
}
}
}
#endregion

#region GetValue 获取键值对
/// <summary>
/// 获取键值对
/// </summary>
public static object GetValue(HttpServerUtilityBase server, string key)
{
string keyMd5 = GetMD5(key);
string folderPath = server.MapPath("~/bin/cache");
string path = folderPath + "\\" + keyMd5 + ".txt";
if (File.Exists(path))
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
CacheData data = (CacheData)formatter.Deserialize(fs);
fs.Close();
FileInfo fileInfo = new FileInfo(data.dependentFilePath);
if (fileInfo.LastWriteTime > data.updateTime)
{
File.Delete(path);
return null;
}
if (data.expirationMinutes > 0 && DateTime.Now.Subtract(data.updateTime).TotalMinutes > data.expirationMinutes)
{
File.Delete(path);
return null;
}
return data.value;
}
}
return null;
}
#endregion

#region Delete 删除
/// <summary>
/// 删除
/// </summary>
public static void Delete(HttpServerUtilityBase server, string key)
{
string keyMd5 = GetMD5(key);
string folderPath = server.MapPath("~/bin/cache");
string path = folderPath + "\\" + keyMd5 + ".txt";
File.Delete(path);
}
#endregion

#region DeleteAll 全部删除
/// <summary>
/// 全部删除
/// </summary>
public static void DeleteAll(HttpServerUtilityBase server)
{
string folderPath = server.MapPath("~/bin/cache");
string[] files = Directory.GetFiles(folderPath);
foreach (string file in files)
{
File.Delete(file);
}
}
#endregion

#region 计算MD5值
/// <summary>
/// 计算MD5值
/// </summary>
private static string GetMD5(string value)
{
string base64 = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(value)).Replace("/", "-");
if (base64.Length > 200)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] bArr = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value));
StringBuilder sb = new StringBuilder();
foreach (byte b in bArr)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
return base64;
}
#endregion
}

#region CacheData 缓存数据
/// <summary>
/// 缓存数据
/// </summary>
[Serializable]
public class CacheData
{
/// <summary>
/// 键
/// </summary>
public string key { get; set; }
/// <summary>
/// 值
/// </summary>
public object value { get; set; }
/// <summary>
/// 缓存更新时间
/// </summary>
public DateTime updateTime { get; set; }
/// <summary>
/// 过期时间(分钟),0表示永不过期
/// </summary>
public int expirationMinutes { get; set; }
/// <summary>
/// 缓存依赖文件路径
/// </summary>
public string dependentFilePath { get; set; }

public CacheData(string key, object value)
{
this.key = key;
this.value = value;
}
}
#endregion

}

View Code

带文件依赖版使用示例:

文件缓存_html文件缓存_键值对_02

public class ProductController : Controller
{
#region details页面
public ActionResult details(string name)
{
ViewBag.menu = "product";

string headKey = "NetCMS.Web.Controllers.ProductController.details.head." + name;
string bodyKey = "NetCMS.Web.Controllers.ProductController.details.body." + name;
string dependentFilePath = Server.MapPath("~/Theme/pages/product/" + name + ".html");

List<string> fileList = Directory.GetFiles(Server.MapPath("~/") + "Theme\\pages\\product").ToList();
string file = fileList.Find(a =>
{
string fileName = Path.GetFileNameWithoutExtension(a);
if (name == fileName)
{
return true;
}
return false;
});

string html = string.Empty;
if (CacheUtil.GetValue(Server, headKey) == null || CacheUtil.GetValue(Server, bodyKey) == null)
{
using (StreamReader sr = new StreamReader(file))
{
html = sr.ReadToEnd();
sr.Close();
}
}

string body = string.Empty;
string pre = "\"" + Url.Content("~/");
body = (string)CacheUtil.GetValue(Server, bodyKey);
if (body == null)
{
Regex reg = new Regex(@"<!--\s*头部结束\s*-->((?:[\s\S])*)<!--\s*公共底部\s*-->", RegexOptions.IgnoreCase);
Match m = reg.Match(html);
if (m.Success)
{
body = m.Groups[1].Value;
}
else
{
body = string.Empty;
}

body = body.Replace("\"js/", pre + "Theme/js/");
body = body.Replace("\"css/", pre + "Theme/css/");
body = body.Replace("\"images/", pre + "Theme/images/");
body = body.Replace("(images/", "(" + Url.Content("~/") + "Theme/images/");
body = body.Replace("('images/", "('" + Url.Content("~/") + "Theme/images/");
body = body.Replace("\"uploads/", pre + "Theme/uploads/");
body = body.Replace("('uploads/", "('" + Url.Content("~/") + "Theme/images/");
body = HtmlUtil.RemoveBlank(body);
CacheUtil.SetValue(Server, bodyKey, body, dependentFilePath);
}

ViewBag.body = body;

string head = string.Empty;
head = (string)CacheUtil.GetValue(Server, headKey);
if (head == null)
{
Regex regHead = new Regex(@"<head>((?:[\s\S])*)</head>", RegexOptions.IgnoreCase);
Match mHead = regHead.Match(html);
if (mHead.Success)
{
head = mHead.Groups[1].Value;
}
else
{
head = string.Empty;
}

head = head.Replace("\"js/", pre + "Theme/js/");
head = head.Replace("\"css/", pre + "Theme/css/");
head = head.Replace("\"images/", pre + "Theme/images/");
head = head.Replace("(images/", "(" + Url.Content("~/") + "Theme/images/");
head = head.Replace("('images/", "('" + Url.Content("~/") + "Theme/images/");
head = head.Replace("\"uploads/", pre + "Theme/uploads/");
head = head.Replace("('uploads/", "('" + Url.Content("~/") + "Theme/images/");
CacheUtil.SetValue(Server, headKey, head, dependentFilePath);
}

ViewBag.head = head;

return View();
}
#endregion

}

View Code