当文件名由的ASP.NET Web API控制器确定如何压缩与IIS缓存文件

问题描述:

我与服务可能很大(< 1-200MB)3D模型下面的控制器操作其中存储的ASP.NET Web API JSON格式到磁盘某处(Web根目录外):当文件名由的ASP.NET Web API控制器确定如何压缩与IIS缓存文件

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或者,在这种情况下,网络API消息处理程序。这是优化CPU使用率以牺牲磁盘空间的最佳方式。

在您的服务器上创建一个目录并保存压缩内容的临时文件。然后,在您的API请求中,检查您的3D模型的压缩文件是否已经创建。如果没有,请立即创建,并将其存储在磁盘上。该模型所要求的结果,下一次将已经被计算,你将只需要返回压缩文件的内容。

// 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因为第一使用较少的内存。知道这个假设模型不会改变也很重要。这也可能是你需要磁盘上的最大容量。