为什么我的自定义交付图像缓存不在浏览器中?

时间:2022-11-22 14:00:50

I have a custom handler that is returning an image to the browser.

我有一个自定义处理程序将图像返回给浏览器。

The images are fetched from a database.

图像是从数据库中提取的。

For some reason the images are not being cached by the browser, and I was wondering if someone might be able to spot what I am missing from the below code:

由于某种原因,浏览器没有缓存图像,我想知道是否有人能够从下面的代码中发现我缺少的内容:

HttpContext.Current.Response.BinaryWrite(imageBytes);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);
Context.Current.Response.Cache.SetAllowResponseInBrowserHistory(true);
if(imgRepGetCache.DateCached.HasValue)
    HttpContext.Current.Response.Cache.SetLastModified(imgRepGetCache.DateCached.Value);
HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddDays(2));
HttpContext.Current.Response.ContentType = "image/jpeg";

Or alternatively if I'm completely missing the point somehow and there's somewhere else I need to look.

或者,如果我以某种方式完全忽略了这一点,那么我还需要寻找其他地方。

Edit: As per request for more info:

编辑:根据请求获取更多信息:

  • The URL is always the same
  • URL始终相同

  • I am testing loading the same file via standard IIS pipe and my pipe in the same browser on the same PC. The one that loads through IIS normally is cached, my file isn't.
  • 我正在测试通过标准IIS管道和我的管道在同一台PC上的同一浏览器中加载相同的文件。通常通过IIS加载的那个是缓存的,我的文件不是。

Edit 2: After inspecting the HTTP requests/responses on the normal IIS route I think it has something to do with the ETag. The ETag (which I'm new to as of just now) seems to be a sort of checksum for the document. On subsequent requests by a browser the ETag is sent and if the server finds the ETag hasn't changed then it returns a 304 - Not Modified. All good! But I'm now setting the ETag using:

编辑2:检查正常IIS路由上的HTTP请求/响应后,我认为它与ETag有关。 ETag(我刚才是新手)似乎是文档的一种校验和。在浏览器的后续请求中,ETag被发送,并且如果服务器发现ETag没有改变,则它返回304-未修改。都好!但我现在使用以下方法设置ETag:

HttpContext.Current.Response.Cache.SetETag(imgRepGetCache.DateCached.ToString());

But it doesn't appear in the response. Closer...

但它没有出现在回复中。言归正传...

Edit 3: I fixed it in the end after taking advantage of Firebug for some HTTP inspecting fun. I posted my solution below.

编辑3:我在利用Firebug进行一些HTTP检查之后最终修复了它。我在下面发布了解决方案。

3 个解决方案

#1


OK, I fixed it.

好的,我修好了。

Here is what I did for anyone else and for my own future reference:

以下是我为其他人做的以及我将来的参考:

// Check for repeated request for the same image from a browser
if (HttpContext.Current.Request.Headers.Get("If-None-Match") == imgRepGetCache.DateCached.Value.ToString())
{
    // Return 304 - Not Modified
    HttpContext.Current.Response.Status = "304 Not Modified";
}
else
{
    if (imgRepGetCache.DateCached.HasValue)
        HttpContext.Current.Response.Headers.Set("Etag", imgRepGetCache.DateCached.Value.ToString());
    // ... do my other stuff here
}

Works a charm!

有魅力!

If anyone spots any potential problems here, let me know so I can update this.

如果有人发现任何潜在问题,请告诉我,以便我可以更新。

To pre-empt one obvious one - I can 100% rely on the date string for identifying whether an image is new or not (in my particular scenario).

为了抢先一个明显的 - 我可以100%依靠日期字符串来识别图像是否是新的(在我的特定场景中)。

#2


You don't mention anything in your post about it, but is this a https:// address? Browsers don't cache images and pages from https sites due to security reasons.

你在帖子中没有提到任何关于它的内容,但这是一个https://地址吗?由于安全原因,浏览器不会缓存来自https站点的图像和页面。

#3


The things you need to worry about in the generation of the response are:

在生成响应时需要担心的事情是:

  • ETag
  • Expires

The things that you need to worry about when receiving a request are:

接收请求时需要担心的事情是:

  • Last-Modified
  • If-Match
  • If-None-Match
  • If-Modified-Since
  • If-Unmodified-Since
  • Unless-Modified-Since

You might also need to worry about the following http methods:

您可能还需要担心以下http方法:

  • GET
  • HEAD

Here is a solution that should be rather easy to refactor to suite your needs: http://code.google.com/p/talifun-web/wiki/StaticFileHandler

这是一个应该很容易重构的解决方案,以满足您的需求:http://code.google.com/p/talifun-web/wiki/StaticFileHandler

It reads files from the file system and them places them into a cache in memory, so just change it to read from database. Should be an easy job.

它从文件系统读取文件,然后将它们放入内存中的缓存中,因此只需将其更改为从数据库中读取即可。应该是一件轻松的工作。

#1


OK, I fixed it.

好的,我修好了。

Here is what I did for anyone else and for my own future reference:

以下是我为其他人做的以及我将来的参考:

// Check for repeated request for the same image from a browser
if (HttpContext.Current.Request.Headers.Get("If-None-Match") == imgRepGetCache.DateCached.Value.ToString())
{
    // Return 304 - Not Modified
    HttpContext.Current.Response.Status = "304 Not Modified";
}
else
{
    if (imgRepGetCache.DateCached.HasValue)
        HttpContext.Current.Response.Headers.Set("Etag", imgRepGetCache.DateCached.Value.ToString());
    // ... do my other stuff here
}

Works a charm!

有魅力!

If anyone spots any potential problems here, let me know so I can update this.

如果有人发现任何潜在问题,请告诉我,以便我可以更新。

To pre-empt one obvious one - I can 100% rely on the date string for identifying whether an image is new or not (in my particular scenario).

为了抢先一个明显的 - 我可以100%依靠日期字符串来识别图像是否是新的(在我的特定场景中)。

#2


You don't mention anything in your post about it, but is this a https:// address? Browsers don't cache images and pages from https sites due to security reasons.

你在帖子中没有提到任何关于它的内容,但这是一个https://地址吗?由于安全原因,浏览器不会缓存来自https站点的图像和页面。

#3


The things you need to worry about in the generation of the response are:

在生成响应时需要担心的事情是:

  • ETag
  • Expires

The things that you need to worry about when receiving a request are:

接收请求时需要担心的事情是:

  • Last-Modified
  • If-Match
  • If-None-Match
  • If-Modified-Since
  • If-Unmodified-Since
  • Unless-Modified-Since

You might also need to worry about the following http methods:

您可能还需要担心以下http方法:

  • GET
  • HEAD

Here is a solution that should be rather easy to refactor to suite your needs: http://code.google.com/p/talifun-web/wiki/StaticFileHandler

这是一个应该很容易重构的解决方案,以满足您的需求:http://code.google.com/p/talifun-web/wiki/StaticFileHandler

It reads files from the file system and them places them into a cache in memory, so just change it to read from database. Should be an easy job.

它从文件系统读取文件,然后将它们放入内存中的缓存中,因此只需将其更改为从数据库中读取即可。应该是一件轻松的工作。