【问题标题】:Static file caching in asp net coreasp net core中的静态文件缓存
【发布时间】:2023-11-06 00:29:01
【问题描述】:

我正在尝试启用静态文件缓存,但似乎没有效果,至少在浏览器中我找不到名称为 cache-control 的响应标头

这是我的代码

        app.UseSpaStaticFiles(new StaticFileOptions
        {
            RequestPath = _settings.SpaRoute,                
        });


            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = ctx =>
                {
                    // Cache static files for 30 days
                    ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=2592000");
                    ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(30).ToString("R", CultureInfo.InvariantCulture));
                }
            });

在本地环境中构建并运行我的应用程序后,我得到了以下响应标头

你可以看到这里没有缓存控制头,我做错了什么?

【问题讨论】:

  • 在此处显示的内容之前是否还有另一个app.UseStaticFiles
  • 另外,Cache-Control 本身就足够了,不需要Expires:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control,或者它不必要的日期算法。
  • 还有另外一个app.UseSpaStaticFiles();之前的中间件
  • 更新后的代码部分
  • 它在您的代码有机会之前将请求短路并发送响应。将OnPrepareResponse 放在您传递给UseSpaStaticFiles 的选项中。

标签: c# asp.net-core caching static-files


【解决方案1】:

StaticFileMiddleware 是一个terminal middleware,即如果遇到与端点不匹配的静态文件请求 (among other conditions),它会短路请求并且永远不会调用链中的下一个中间件。

这意味着如果您多次调用app.UseStaticFiles(),它将在中间件链中多次插入StaticFileMiddleware,并且只有链中的第一个将处理请求,其余的将保持休眠状态。

在控制器动作中放置一个断点并检查调用堆栈,看看堆栈中是否有多个StaticFileMiddleware。如果这样做,请删除未使用的配置,或将此处的配置移至第一个配置。

在你的代码中,你似乎有app.UseSpaStaticFiles, which calls app.UseStaticFiles,所以它在你自己的app.UseStaticFiles(/*custom options*/)之前生效。

要解决这个问题,只需将OnPrepareResponse 传递到该中间件:

app.UseSpaStaticFiles(new StaticFileOptions {
    RequestPath = _settings.SpaRoute, 
    OnPrepareResponse = ctx =>
    {
        // Cache static files for 30 days
        ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=2592000");
    }               
});

【讨论】:

  • 还有一个问题,假设我的主站点有一张图片,我将这张图片缓存了 1 年,因为我很长一段时间都不会更改。但是过了一段时间,有一天我决定改变那个图像并再拍一张,在这种情况下我该怎么办?是否有一种机制来确定该文件是否已更改并加载新文件并缓存它?
  • 您可以为该资产添加版本后缀,该后缀每次更改时都会更改。一旦资产 URL 更改,浏览器将获取新文件并缓存它。对于 Razor 模板,您有 asp-append-version tag helper。对于 UI 框架,这取决于您使用什么。如果您使用的是 webpack,您可以将版本/哈希添加到文件名 webpack.js.org/guides/caching
  • 如果一切都失败了,你可以简单地自己附加一个版本:<img src="logo.svg" /> -> <img src="logo.svg?v=20210722" />
  • 谢谢,你能解释一下这个公众背后的逻辑吗,max-age=2592000 = 30 天?如果我只想缓存 3 天怎么办?这个算法应该如何计算?
  • 你需要以秒为单位指定持续时间:(3 days) * (24hr / day) * (60min / hr) * (60sec / min) = 259200 sec -> 所以你需要使用public,max-age=259200。至于其他指令的含义,MDN 是一个很好的起点。 developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
最近更新 更多