CDN для изображений в ASP.NET - PullRequest
2 голосов
/ 27 марта 2010

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

Моей первой мыслью было добавить HttpHandler для расширений изображений, которые в зависимости от того, будет ли переменная в файле web.config (что-то подобное) обслуживать изображение с сервера или из CDN. Но, немного поработав, я думаю, что по сути исключил это, так как это заставит ASP.NET обработать запрос для каждого отдельного образа, добавив таким образом накладные расходы, и это может фактически полностью уменьшить преимущества использования CDN.

Альтернативный подход заключается в том, что, поскольку все мои страницы наследуются от базового класса страниц, я мог бы создать функцию в базовом классе, которая определяет путь для обслуживания файлов на основе переменной web.config. Я бы тогда сделал что-то подобное в разметке:

<img src='<%= GetImagePath()/image.png' />

Я думаю, что это, вероятно, то, что мне придется в конечном итоге сделать, но мне это кажется немного неуклюжим. Я также предполагаю проблемы со старой ошибкой .NET из-за невозможности изменить коллекцию элементов управления из-за "<% =", хотя решение "<% #", вероятно, будет работать. </p>

Есть мысли или идеи о том, как это реализовать?

Ответы [ 9 ]

2 голосов
/ 29 марта 2010

Рассматривали ли вы немного более простой подход?

Если все ваши страницы наследуются от базового класса, вы можете выставить свойство для того, который содержит предварительно добавленный URL к вашему CDN (или к вашему локальному серверу, если вы хотите отключить CDN). Затем достаточно просто сохранить предварительно добавленный URL в файле web.config:

public string PrependURLPath() {
 get { return ConfigurationManager.AppSettings["ImagePrependURL"].ToString(); }
}

В вашем элементе <appSettings/> вы можете просто выбрать, каким будет предварительно добавленный URL-адрес, например:

http://my.cdn.com/user/

или:

http://my.own.server.com/images/

Довольно просто!

После этого вы сможете закодировать ссылки на изображения в соответствии с вашим примером, но вызовите свойство базовой страницы, чтобы указать нужный путь:

<img src='<%= this.BasePage.PrependURLPath() + [YourImagePath.png] %>'/>

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

Даже если ваши страницы в настоящее время наследуются только от System.Web.UI.Page, просто создать собственный базовый класс, который наследует System.Web.Page, а затем выполнить поиск / замену в своем решении на всех оставшихся страницах. .

Надеюсь, это поможет.

2 голосов
/ 07 марта 2011

взвешивается здесь довольно поздно, но я сам искал подобное решение. искал гугл в здравомыслие проверь что я сделал. я не учел подход HttpHandler, я просто расширил элемент управления ASP.net Image:

public class Img : Image
{
    public Img()
    {
        RelativePath = false;
    }

    public bool RelativePath { get; set; }

    public override string ImageUrl
    {
        get
        {
            if (RelativePath)
                return base.ImageUrl;

            return "http://some.configurable-value.com" + base.ImageUrl;
        } 
        set { base.ImageUrl = value; }
    }
}

это грубо и готово, но работает :), очевидно, оно должно полагаться на какое-то настраиваемое значение, а не на строковый литерал, но это не большое изменение

2 голосов
/ 27 марта 2010

Вы отклонили написание HttpHandler на основании предположения о предварительной оптимизации. Я хотел бы вернуться к этому и обязательно написать простой HttpHandler и проверить его. Вы можете обнаружить, что ваше решение метода Page может быть даже медленнее, особенно если вы задействуете препроцессор ASP.

HttpHandlers довольно близки к металлу - это небольшая нагрузка на IIS для передачи запроса ASP.Net. Это было бы более элегантное решение, чем то, что вы предлагаете, и, вероятно, более масштабируемое, и я готов поспорить - быстрее.

1 голос
/ 31 марта 2010

Если вы отображаете свои изображения, используя теги, вы можете создать адаптер управления, это позволит вам изменить способ визуализации элементов управления .net или повсеместно изменить их примерно так:

using System.Web.UI.WebControls.Adapters;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ExampleCode
{
    public class ImageAdapter : WebControlAdapter
    {
        private bool UseCdn
        {
            get { return true; } // Get value from config or anywhere else
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            Image image = (Image)Control;

            if (UseCdn)
            {
                // If using relative urls for images may need to handle ~
                image.ImageUrl = String.Format("{0}/{1}", "CDN URL", image.ImageUrl);
            }
         }
      }
 }

Затем добавьте файл браузера в папку App_Browsers в вашем веб-проекте, как показано ниже:

<browsers>
    <browser refID="Default">
      <controlAdapters>
        <adapter
          controlType="System.Web.UI.WebControls.Image"
          adapterType="ExampleCode.ImageAdapter"
          />
      </controlAdapters>
    </browser>
</browsers>
0 голосов
/ 19 декабря 2015

Мне пришлось решить вашу проблему и еще одну, то есть я не хочу брать ресурсы из CDN во время разработки, а только когда веб-сайт развернут на рабочем сервере. Чтобы решить эту проблему, я разработал ExpressionBuilder, который добавляет URL-адрес CDN только в рабочем состоянии.

<asp:Image ImageUrl="<%$ CdnUrl:/images/myimage.png %>" runat="server" />

В предыдущем коде URL CDN будет добавляться только в рабочей.

namespace IdeaR.Web.Compilation
{
[ExpressionPrefix("CdnUrl")]
public class CdnUrlExpressionBuilder : ExpressionBuilder
{
    public static object GetCdnUrl(string expression, Type target, string entry)
    {
        var retvalue = expression;
        var productionUri = new Uri("http://www.myproductionurl.com",
            UriKind.Absolute);
        var currentUri = HttpContext.Current.Request.Url;
        var cdnUrl = "http://cdn.mycdn.com";

        // If this is a production website URL
        if (currentUri.Scheme == productionUri.Scheme &&
            currentUri.Host == productionUri.Host)
            retvalue = cdnUrl + expression;

        return retvalue;
    }

    public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,
        object parsedData, ExpressionBuilderContext context)
    {
        var componentType = entry.DeclaringType;
        var expressionArray = new CodeExpression[3]
        {
            new CodePrimitiveExpression(entry.Expression.Trim()),
            new CodeTypeOfExpression(componentType),
            new CodePrimitiveExpression(entry.Name)
        };

        var descriptor = TypeDescriptor.GetProperties(componentType)
            [entry.PropertyInfo.Name];
        return new CodeCastExpression(descriptor.PropertyType,
            new CodeMethodInvokeExpression(
                new CodeTypeReferenceExpression(GetType()),
                "GetCdnUrl", expressionArray));
    }       
}
}

Для получения дополнительной информации я написал статью об этом Как использовать CDN в производстве, но не во время разработки

0 голосов
/ 02 декабря 2011

Не похоже, что был принят ответ, так что вот мое предложение. У меня были похожие проблемы, связанные с прозрачным изменением URL (с другой стороны, но я подумал и об использовании его для поддержки CDN).

Это старый фильтр / модуль, но он работал хорошо для моих нужд с небольшой настройкой: http://www.paraesthesia.com/archive/2007/12/14/urlabsolutifiermodule---convert-urls-in-asp.net-output-to-absolute.aspx

Что вы можете сделать, так это создать фильтр ответов и подключить его к http-модулю (как это делает этот абсолютификатор). Если вы используете этот модуль + фильтр ответов, вы, вероятно, сможете добиться того, что вам нужно, изменив источник для него, чтобы заменить имя хоста / префикс всех URL-адресов для использования CDN.

0 голосов
/ 14 января 2011

Я пойду на подход @Rhys для управления изображением.

В большинстве случаев я пытаюсь использовать css для фонового изображения, а не для управления изображением.

После этого я загружаю css и изображения вместе в облако и нормально работаю для относительного пути.

0 голосов
/ 29 марта 2010

Хорошая особенность подхода HTTP Handler заключается в том, что его можно многократно использовать и настраивать: вы можете определять пути img для обработки в зависимости от местоположения - при условии, что структура, в которой они находятся, помогает.

Возможным недостатком является то, что расширения файлов изображений (.jpg, .png и т. Д.) Не передаются автоматически в конвейер asp.net; вы можете легко настроить IIS для этого - но вам нужно иметь определенный уровень контроля над IIS - так что это может не подойти, если вы находитесь в среде общего хостинга.

0 голосов
/ 27 марта 2010

Вы можете зациклить все элементы управления и изменить URL-адрес изображения в событии prerender в вашем базовом классе ...

...