2010-03-27 2 views
2

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

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

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

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

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

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

ответ

0

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

2

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

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

+0

Да, я не знаю, почему я даже не понял, что второй подход получает процесс ASP.net участие. , , довольно легкомысленно с моей стороны. На мой взгляд, моя самая большая проблема заключается в том, что каждый запрос изображения запрашивал бы изображение из CDN и, возможно, уменьшал бы кеширование на стороне клиента, выполненное из заголовков ответов CDN? Я не знаю достаточно о том, что происходит под капотом, чтобы сделать это определение. – Chris

+0

Если ваш сервер HttpHandler передает данные изображения, вы не получаете никакой экономии в использовании полосы пропускания от использования CDN. Другой вариант - позволить вашему HttpHandler отправлять 302 версии CDN того же URL-адреса. – David

0

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

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

2

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

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

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, затем найдет/заменит ваше решение на всех остальных страницы.

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

1

Если вы показываете ваши изображения с помощью тегов вы можете создать адаптер управления, они позволяют изменить способ управления .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

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

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

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

2

весом здесь довольно поздно, но я сам искал подобное решение. искал google, чтобы проверить, что я сделал. не считал 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; } 
    } 
} 

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

0

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

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

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

0

Мне пришлось решить вашу проблему и еще одну, то есть я не хочу извлекать ресурсы из 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)); 
    }  
} 
} 

Для получения дополнительной информации, которую я написал статью об этом How to use a CDN in production but not during development

Смежные вопросы