Потоковая обработка изображений с использованием HttpHandler

В течение долгого времени я заметил что-то раздражающее при работе над проектами веб-приложений, связанными с изображениями на базе данных на моей локальной машине. По локальному я имею в виду, что это типичная среда с VS 2008 и SQL Server 2005 на моей рабочей станции. Всякий раз, когда я использую HttpHandler для отображения изображений на моем локальном уровне, только некоторые изображения отображаются на каждой загрузке страницы.

Однако, когда я нажимаю приложение в размещенную среду, проблема обычно исчезает. Однако я просто вытолкнул новый проект в размещенную среду и испытал ту же проблему, что и на моем локальном уровне - на этот раз сайт и БД находились на одном сервере в среде хостинга. Кто-нибудь взял на себя то, что здесь происходит?

Здесь обработчик:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class FeaturedHandler : IHttpHandler
{
    Business biz = new Business();

    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.QueryString["ListingID"] != null)
        {
            int listingID = Convert.ToInt32(context.Request.QueryString["ListingID"]);

            DataSet ds = biz.GetFeaturedImageByID(listingID);
            DataRow row = ds.Tables[0].Rows[0];
            byte[] featureImage = (byte[])row["Photo"];
            context.Response.ContentType = "image/jpeg";
            context.Response.OutputStream.Write(featureImage, 0, featureImage.Length);
        }
        else
            throw new ArgumentException("No ListingID parameter specified");
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
} 

Я попытался использовать БД на отдельном сервере, но столкнулся с той же проблемой. Должен ли я использовать DataReader вместо этого?

UPDATE Я должен был использовать DataReader изначально, так как я читаю двоичные данные.

Ответ 1

Наконец, я получил все изображения для рендеринга, изменив значение свойства IsReusable на true:

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }

По-видимому, это удерживает обработчик в памяти и способно обрабатывать несколько запросов. Когда установлено значение false, ему нужно было создать новый экземпляр обработчика для каждого входящего запроса.

Ответ 2

Таким образом:

Всякий раз, когда я использую HttpHandler для отображать изображения на моем локальном, только часть изображений, отображаемых на каждом Загрузка страницы.

Вы имеете в виду, что одно и то же изображение появляется в местах, где должны отображаться разные изображения или появляются некоторые изображения, а некоторые вообще не отображаются?

В вашем случае разница при переключении isReusable в true заключается в том, что new Business(); будет вызываться один раз для нескольких изображений. Если isReusable false, new Business(); будет вызываться один раз для каждого изображения. Это означает, что если у вас есть несколько изображений на странице new Business();, вызывается несколько раз для этой конкретной страницы.

Также я настоятельно рекомендую изменить это:

if (context.Request.QueryString["ListingID"] != null)
{
    int listingID = Convert.ToInt32(context.Request.QueryString["ListingID"]);

с:

string listingIdParam = context.Request.QueryString["ListingID"];
if (listingIdParam != null)
{
    int listingID = Convert.ToInt32(listingIdParam);

Это избавит вас от нулевых ссылочных исключений, которые обычно появляются только при большой нагрузке. Также вышесказанное предотвратит неправильное обращение к запросу, особенно когда isReusable является истинным.

Я не могу определить, в чем проблема, но я могу определенно сказать, что установка флага isReusable была всего лишь обходным решением и не устраняет вашу проблему. Также, когда подобная проблема воспроизводится только в определенной среде, это означает, что либо это проблема потока, либо есть некоторая разница в обработке запросов (другой веб-сервер - IIS6, IIS7, сервер разработки).

Возможно публикация класса Business, и конструктор может пролить некоторый свет. Кроме того, я предлагаю внедрить некоторую регистрацию ошибок для исключения ошибок в обработчике и их просмотра.

Ответ 3

Если вы обслуживаете изображения напрямую, не забудьте установить правильные заголовки кеширования, т.е. etags и срок действия. Если вы этого не сделаете, вы действительно сильно ударяете свою базу данных и используете свою пропускную способность.

Вам нужно будет обрабатывать следующие заголовки http:

  • ETag
  • Истекает
  • Last-Modified
  • Если-Match
  • If-None-Match
  • If-Modified-Since
  • Если-Unmodified-С
  • Unless-Modified-Since

Для примера обработчик http, который делает это: http://code.google.com/p/talifun-web/wiki/StaticFileHandler