private Task handleResource(IOwinContext context, Stream stream, DateTime?lastModified, string path, double expires, IDictionary <string, string> addonHttpHeaders) { var req = context.Request; var rep = context.Response; //验证缓存有效 if (lastModified.HasValue) { //=================== //先验证最后修改时间 //=================== var resourceLastModified = lastModified.Value; //最后修改时间判断部分 var clientLastModified = req.Headers.Get("If-Modified-Since"); if (clientLastModified != null) { if (clientLastModified == resourceLastModified.ToString("R")) { rep.StatusCode = 304; return(Task.Run(() => stream.Dispose())); } } //=================== //然后验证ETag //=================== //ETag设置判断部分 String serverETag = null; if (UseMd5ETag) { serverETag = HashUtils.ComputeETagByMd5(stream); if (stream.CanSeek) { stream.Position = 0; } } else { serverETag = lastModified.Value.Ticks.ToString(); } var clientETag = req.Headers.Get("If-None-Match"); //如果客户端的ETag值与服务端相同,则返回304,表示资源未修改 if (serverETag == clientETag) { rep.StatusCode = 304; return(Task.Run(() => stream.Dispose())); } rep.ETag = serverETag; } rep.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(expires)); rep.Headers["Cache-Control"] = $"max-age={expires}"; if (lastModified.HasValue) { rep.Headers["Last-Modified"] = lastModified.Value.ToUniversalTime().ToString("R"); } return(context.Output(stream, true, EnableCompress, path, addonHttpHeaders)); }