2017-02-15 24 views
2

У меня есть веб-API ASP.NET со следующим действием контроллера для обслуживания, возможно, больших (< 1-200 МБ) 3D-моделей, которые хранятся в формате JSON где-то на диске (за пределами веб-корень):Как сжимать и кэшировать файлы с помощью IIS, когда имя файла определяется контроллером ASP.NET Web API

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) не кэширует сжатые результаты, поэтому он должен повторно компилировать s соответствующий файл для каждого запроса. Я ожидаю, что он не кэшируется, потому что контроллер считывает JSON в память и обслуживает его как StringContent.

Я почти ничего не знаю о IIS и немного об ASP.NET Web API. Как я могу лучше всего обслуживать файлы JSON, чтобы они были сжаты И убедитесь, что IIS кэширует сжатые результаты, чтобы их не нужно было повторно сжимать каждый раз? (И если по какой-то причине это звучит как плохая идея, что я должен делать?)

ответ

1

Я предлагаю создать кэш, на котором у вас есть полный контроль над ним, вместо делегирования сжатия IIS или, в этом случае, Web Обработчики сообщений API. Это лучший способ оптимизировать использование ЦП, жертвуя дисковым пространством.

Создайте каталог на своем сервере и сохраните временные файлы со сжатым контентом. Затем в вашем запросе 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, потому что первый использует меньше памяти. Также важно знать, что это предполагает, что модели не будут меняться. Вероятно, для этого вам понадобится максимальная емкость на диске.