我正在使用 .aspx 页面根据给定的参数从文件系统中提供图像文件。
Server.Transfer(imageFilePath);
当此代码运行时,会提供图像,但不会创建Last-Modified HTTP 标头。与同一个文件相反,直接从同一服务器上的 URL 调用。
因此浏览器不会发出If-Modified-Since并且不会缓存响应。
有没有办法让服务器像通常直接请求文件(在这种情况下为图像)一样创建 HTTP 标头,还是我必须手动创建标头?
我正在使用 .aspx 页面根据给定的参数从文件系统中提供图像文件。
Server.Transfer(imageFilePath);
当此代码运行时,会提供图像,但不会创建Last-Modified HTTP 标头。与同一个文件相反,直接从同一服务器上的 URL 调用。
因此浏览器不会发出If-Modified-Since并且不会缓存响应。
有没有办法让服务器像通常直接请求文件(在这种情况下为图像)一样创建 HTTP 标头,还是我必须手动创建标头?
当您对文件进行传输时,服务器将返回与文件相同的标头.aspx
,因为它基本上是由 .NET 引擎执行的。
你基本上有两个选择:
改为重定向到文件,以便浏览器发出请求。
设置您想要的标题,并使用Request.BinaryWrite
(或类似)在响应中将文件数据发送回。
我将扩展@Guffa 的答案并分享我选择的解决方案。
调用该Server.Transfer
方法时,.NET 引擎将其视为一个.aspx
页面,因此在提供静态文件时它不会添加所需的适当 HTTP 标头(例如用于缓存)。
有三个选项
Response.Redirect
,因此浏览器发出适当的请求Request.BinaryWrite
用于提供内容Server.Transfer
我选择第三个选项,这是我的代码:
try
{
DateTime fileLastModified = File.GetLastWriteTimeUtc(MapPath(fileVirtualPath));
fileLastModified = new DateTime(fileLastModified.Year, fileLastModified.Month, fileLastModified.Day, fileLastModified.Hour, fileLastModified.Minute, fileLastModified.Second);
if (Request.Headers["If-Modified-Since"] != null)
{
DateTime modifiedSince = DateTime.Parse(Request.Headers["If-Modified-Since"]);
if (modifiedSince.ToUniversalTime() >= fileLastModified)
{
Response.StatusCode = 304;
Response.StatusDescription = "Not Modified";
return;
}
}
Response.AddHeader("Last-Modified", fileLastModified.ToString("R"));
}
catch
{
Response.StatusCode = 404;
Response.StatusDescription = "Not found";
return;
}
Server.Transfer(fileVirtualPath);