当文件名由 ASP.NET Web API 控制器确定时如何使用 IIS 压缩和缓存文件
How to compress and cache files with IIS when filename is determined by ASP.NET Web API controller
我有一个 ASP.NET Web API,它具有以下控制器操作,用于提供可能以 JSON 格式存储在磁盘某处的大型 (<1-200MB) 3D 模型(在网络根之外):
public HttpResponseMessage GetModel(Guid accessToken, Guid modelId)
{
Guid projectId = MyBackend.Validate(accessToken);
string fileName = MyPaths.GetModelFile(projectId, modelId);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(File.ReadAllText(fileName),
Encoding.UTF8, "application/json");
return response;
}
在我的 Global.asax 中有这一行:
GlobalConfiguration.Configuration.MessageHandlers.Insert(
0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));
当我调用 API 端点时,内容按预期进行了 gzip 压缩,但 IIS (8.5) 不缓存压缩结果,因此它必须为每个请求重新压缩相关文件。我希望它没有被缓存,因为控制器将 JSON 读入内存并将其用作 StringContent
.
我对 IIS 几乎一无所知,对 ASP.NET Web API 知之甚少。我怎样才能最好地提供 JSON 文件以便压缩它们并确保 IIS 缓存压缩结果,这样它们就不必每次都重新压缩? (如果出于某种原因这听起来不是个好主意,我应该怎么做?)
我建议创建一个您可以完全控制它的缓存,而不是将压缩委托给 IIS,或者在本例中,Web API 消息处理程序。这是优化 CPU 使用牺牲磁盘 space 的最佳方式。
在您的服务器上创建一个目录,并在其中保存包含压缩内容的临时文件。然后,在您的 API 请求中,检查您的 3D 模型的压缩文件是否已经创建。如果没有,请即时创建它,并将其存储在磁盘上。下次请求模型时,结果已经计算出来,您只需要 return 压缩文件内容。
// Calculate a path for your cache file.
var compressedCacheFilename = GetCachePath(filename);
Stream compressedStream;
if (File.Exists(compressedCacheFilename)) {
compressedStream = new FileStream(compressedCacheFilename, FileMode.Open, FileAccess.Read);
}
else {
/* Use the best compression algorithm for your data
and store it to the corresponding path. */
compressedStream = compressor.CompressTo(
new FileStream(filename, FileMode.Open, FileAccess.Read),
compressedCacheFilename
);
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(compressedStream);
response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
response.Content.Headers.ContentEncoding.Clear();
response.Content.Headers.ContentEncoding.Add("gzip"); // your compression algorithm
请注意,在代码示例中,我使用 StreamContent
而不是 StringContent
,因为第一个使用的内存较少。同样重要的是要知道这是假设模型不会改变。为此,您也可能需要磁盘的最大容量。
我有一个 ASP.NET Web API,它具有以下控制器操作,用于提供可能以 JSON 格式存储在磁盘某处的大型 (<1-200MB) 3D 模型(在网络根之外):
public HttpResponseMessage GetModel(Guid accessToken, Guid modelId)
{
Guid projectId = MyBackend.Validate(accessToken);
string fileName = MyPaths.GetModelFile(projectId, modelId);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(File.ReadAllText(fileName),
Encoding.UTF8, "application/json");
return response;
}
在我的 Global.asax 中有这一行:
GlobalConfiguration.Configuration.MessageHandlers.Insert(
0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));
当我调用 API 端点时,内容按预期进行了 gzip 压缩,但 IIS (8.5) 不缓存压缩结果,因此它必须为每个请求重新压缩相关文件。我希望它没有被缓存,因为控制器将 JSON 读入内存并将其用作 StringContent
.
我对 IIS 几乎一无所知,对 ASP.NET Web API 知之甚少。我怎样才能最好地提供 JSON 文件以便压缩它们并确保 IIS 缓存压缩结果,这样它们就不必每次都重新压缩? (如果出于某种原因这听起来不是个好主意,我应该怎么做?)
我建议创建一个您可以完全控制它的缓存,而不是将压缩委托给 IIS,或者在本例中,Web API 消息处理程序。这是优化 CPU 使用牺牲磁盘 space 的最佳方式。
在您的服务器上创建一个目录,并在其中保存包含压缩内容的临时文件。然后,在您的 API 请求中,检查您的 3D 模型的压缩文件是否已经创建。如果没有,请即时创建它,并将其存储在磁盘上。下次请求模型时,结果已经计算出来,您只需要 return 压缩文件内容。
// Calculate a path for your cache file.
var compressedCacheFilename = GetCachePath(filename);
Stream compressedStream;
if (File.Exists(compressedCacheFilename)) {
compressedStream = new FileStream(compressedCacheFilename, FileMode.Open, FileAccess.Read);
}
else {
/* Use the best compression algorithm for your data
and store it to the corresponding path. */
compressedStream = compressor.CompressTo(
new FileStream(filename, FileMode.Open, FileAccess.Read),
compressedCacheFilename
);
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(compressedStream);
response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
response.Content.Headers.ContentEncoding.Clear();
response.Content.Headers.ContentEncoding.Add("gzip"); // your compression algorithm
请注意,在代码示例中,我使用 StreamContent
而不是 StringContent
,因为第一个使用的内存较少。同样重要的是要知道这是假设模型不会改变。为此,您也可能需要磁盘的最大容量。