Blazor WebAssembly 提供了一个缓存管理 API,可以帮助我们进行离线模式下的静态文件下载。首先,我们需要在 Program.cs
文件中启用离线模式,并为缓存管理器提供一个有意义的名称:
using System.Net.Http;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Caching.Memory;
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// 启用离线模式
builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.RootComponents.Add("app");
builder.Services.AddMemoryCache();
builder.Services.AddHttpClient("offline-cache")
.ConfigureHttpClient(client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip })
.AddHttpMessageHandler();
await builder.Build().RunAsync();
}
}
public class CacheHandler : DelegatingHandler
{
private const string CacheHeaderName = "X-Blazor-Cache";
private readonly IMemoryCache cache;
public CacheHandler(IMemoryCache cache)
{
this.cache = cache;
}
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// 检查是否离线模式
if (!request.Headers.TryGetValues(CacheHeaderName, out var cacheHeaders))
{
return await base.SendAsync(request, cancellationToken);
}
var cacheKey = request.RequestUri.PathAndQuery;
if (cache.TryGetValue(cacheKey, out var cachedResponse))
{
return (HttpResponseMessage)cachedResponse;
}
var result = await base.SendAsync(request, cancellationToken);
if (result.IsSuccessStatusCode)
{
var cacheControl = cacheHeaders.SelectMany(x => x.Split(',', StringSplitOptions.RemoveEmptyEntries))
.Select(x => x.Trim().ToLowerInvariant())
.FirstOrDefault(x => x.StartsWith("max-age="));
if (int.TryParse(cacheControl?.Substring("max-age