你好,我刚开始使用ASP.NET MVC 4,我在一家企业实习,该企业告诉我在没有服务器的情况下创建一个基本的webshop然后用YSlow验证HTML和网站的速度。
我一直很忙,当我完成网店时,我开始使用YSlow将速度应用到网站上,但有一件事我似乎无法解决,那就是配置错误的ETag:
"有5个组件的ETags配置错误"<-这些是我的CSS文件和我使用过的图片。我一直在研究ETag是什么,但仍然不知道它们是做什么的。
我知道在Apache中,你可以说FileETag none来关闭它们,但在这种情况下,我没有使用服务器,我仍然想关闭它们,因为它们对99分不满意。
我正在寻找的是ETag到底做了什么的答案,以及我的问题的解决方案。
感谢
根据下面的评论,这是一个练习,显然PC的性能不会很好。您可以使用httpHandler。这是我用于图像的一个,它将有助于你的yslow(但请注意,这并不能保证性能,而且是为了指导非常繁忙的网站)
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetMaxAge(new TimeSpan(28, 0, 0, 0, 0));
// Setting the last modified date to the creation data of the assembly
Assembly thisAssembly = Assembly.GetExecutingAssembly();
string thisPath = thisAssembly.CodeBase.Replace(@"file:///", "");
string assemblyName = "yourAssembly";
string assemblyPath = thisPath.Replace(thisAssembly.ManifestModule.ScopeName, assemblyName);
var assemblyInfo = new FileInfo(assemblyPath);
var creationDate = assemblyInfo.CreationTime;
string eTag = GetFileETag(assemblyPath, creationDate);
// set cache info
context.Response.Cache.SetCacheability(HttpCacheability.Private);
context.Response.Cache.VaryByHeaders["If-Modified-Since"] = true;
context.Response.Cache.VaryByHeaders["If-None-Match"] = true;
context.Response.Cache.SetLastModified(creationDate);
context.Response.Cache.SetETag(eTag);
if (IsFileModified(assemblyPath, creationDate, eTag, context.Request))
{
//context.Response.ContentType = <specify content type>;
// Do resource processing here
context.Response.TransmitFile(context.Request.PhysicalPath);
}
else
{
// File hasn't changed, so return HTTP 304 without retrieving the data
context.Response.StatusCode = 304;
context.Response.StatusDescription = "Not Modified";
// Explicitly set the Content-Length header so the client doesn't wait for
// content but keeps the connection open for other requests
context.Response.AddHeader("Content-Length", "0");
}
context.Response.End();
}
public bool IsReusable
{
get { return false; }
}
/// <summary>
/// Checks if the resource assembly has been modified based on creation date.
/// </summary>
/// <remarks>
/// </remarks>
/// <seealso cref="GetFileETag"/>
private bool IsFileModified(string fileName, DateTime modifyDate, string eTag, HttpRequest request)
{
// Assume file has been modified unless we can determine otherwise
bool FileDateModified = true;
DateTime ModifiedSince;
TimeSpan ModifyDiff;
bool ETagChanged;
// Check If-Modified-Since request header, if it exists
string ifModifiedSince = request.Headers["If-Modified-Since"];
if (!string.IsNullOrEmpty(ifModifiedSince) && ifModifiedSince.Length > 0 && DateTime.TryParse(ifModifiedSince, out ModifiedSince))
{
FileDateModified = false;
if (modifyDate > ModifiedSince)
{
ModifyDiff = modifyDate - ModifiedSince;
// Ignore time difference of up to one seconds to compensate for date encoding
FileDateModified = ModifyDiff > TimeSpan.FromSeconds(1);
}
}
// Check the If-None-Match header, if it exists. This header is used by FireFox to validate entities based on the ETag response header
ETagChanged = false;
string ifNoneMatch = request.Headers["If-None-Match"];
if (!string.IsNullOrEmpty(ifNoneMatch) && ifNoneMatch.Length > 0)
{
ETagChanged = ifNoneMatch != eTag;
}
return ETagChanged || FileDateModified;
}
/// <summary>
/// Generates a caching ETag based on file name and creation date.
/// </summary>
/// <remarks>
/// </remarks>
/// <seealso cref="GetFileETag"/>
private string GetFileETag(string fileName, DateTime modifyDate)
{
string fileString;
Encoder stringEncoder;
int byteCount;
Byte[] stringBytes;
// Use file name and modify date as the unique identifier
fileString = fileName + modifyDate.ToString();
// Get string bytes
stringEncoder = Encoding.UTF8.GetEncoder();
byteCount = stringEncoder.GetByteCount(fileString.ToCharArray(), 0, fileString.Length, true);
stringBytes = new Byte[byteCount];
stringEncoder.GetBytes(fileString.ToCharArray(), 0, fileString.Length, stringBytes, 0, true);
//{ Hash string using MD5 and return the hex-encoded hash }
MD5 Enc = MD5CryptoServiceProvider.Create();
return """ + BitConverter.ToString(Enc.ComputeHash(stringBytes)).Replace("-", string.Empty) + """;
}
}
}
然后在配置中指定处理程序(如果不使用iis7,也可以在httphandlers下执行)
<add name="pngs" verb="*" path="*.png" type="yourAssembly.HttpHandlers.ImageHandler, hcs.web" preCondition="managedHandler" />
<add name="jpgs" verb="*" path="*.jpg" type="yourAssembly.HttpHandlers.ImageHandler, hcs.web" preCondition="managedHandler" />
<add name="gif" verb="*" path="*.gif" type="yourAssembly.HttpHandlers.ImageHandler, hcs.web" preCondition="managedHandler" />