Получение изображения из HTTPRuntime Cache

Я пытаюсь сохранить и получить изображение из HTTPRuntime Cache, но получаю исключение. Я могу сохранить поток в кэш, но когда я пытаюсь получить его, я получаю исключение:

запрос был прерван. Соединение было неожиданно закрыто

Вот мой код:

public void ProcessRequest(HttpContext context)
{   
    string courseKey = context.Request.QueryString["ck"];
    string objKey = context.Request.QueryString["file"];

    if(HttpRuntime.Cache[objKey] !=null)
    {
        using (Stream stream = (Stream)HttpRuntime.Cache[objKey]) // here is where I get an exception
        {
            var buffer = new byte[8000];
            var bytesRead = -1;
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                context.Response.OutputStream.Write(buffer, 0, bytesRead);
            }
        }
        return;
    }
    var response = Gets3Response(objKey, courseKey, context);           

    if (response != null)
    {
        using (response)
        {
            var MIMEtype = response.ContentType;
            context.Response.ContentType = MIMEtype;
            var cacheControl = context.Response.CacheControl;
            HttpRuntime.Cache.Insert(objKey, response.ResponseStream, null, DateTime.UtcNow.AddMinutes(20), Cache.NoSlidingExpiration);
            using (Stream responseStream = response.ResponseStream)
            {
                var buffer = new byte[8000];
                var bytesRead = -1;
                while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                   context.Response.OutputStream.Write(buffer, 0, bytesRead);
                }
            }
        }
    }
}

И вот исключение, которое я получаю

исключение

1 ответ

Решение

Этот код довольно запутанный. Во-первых, вы кешируете response.ResponseStream, но это было завернуто в using блок. Таким образом, к тому времени, когда вы доберетесь до HttpRuntime.Cache.Insert, response.ResponseStream уже будет удален и закрыт. Отсюда и ошибка.

Вы не должны кэшировать поток. С одной стороны, как только вы разместите службу распределенного кэша, ваш подход станет невозможным. Вы должны рефакторинг это. Рассматривать:

public class CacheAsset
{
   public string FileName { get; set; }
   public string ContentType { get; set; }
   public byte[] Content { get; set; }
}

CacheAsset GetAsset(HttpContext context)
{
   string courseKey = context.Request.QueryString["ck"];
   string objKey = context.Request.QueryString["file"];

   var asset = context.Cache[objKey] as CacheAsset;

   if (asset != null) return asset;

   using (var response = Gets3Response(objKey, courseKey, context))
   using (var stream = new MemoryStream())
   { 
      var buffer = new byte[8000];
      var read = 0;

      while ((read = response.ReponseStream.Read(buffer, 0, buffer.Length)) > 0)
      {
         stream.Write(buffer, 0, read);
      }

      asset = new CacheAsset
              {
                 FileName = objKey,
                 ContentType = reponse.ContentType,
                 Content = stream.ToArray()
              };
       context.Cache.Insert(objKey, asset, null, DateTime.UtcNow.AddMinutes(20), Cache.NoSlidingExpiration);
   }

   return asset;
}

public void ProcessRequest(HttpContext context)
{
   var asset = GetAsset(context);

   context.Response.ContentType = asset.ContentType;
   context.Response.BinaryWrite(asset.Content);
}
Другие вопросы по тегам