Наличие картинки на другом сайте.
Например: http://www.xxx.com/images/IconsCatalog/test.jpg
Как в коде проверить наличие этой картинку у них на сайте?
Что то вроде: File.Exists(???)
Только вместо физического пути нужно указать http.
Как это сделать?
Например: http://www.xxx.com/images/IconsCatalog/test.jpg
Как в коде проверить наличие этой картинку у них на сайте?
Что то вроде: File.Exists(???)
Только вместо физического пути нужно указать http.
Как это сделать?
Вот так можно загрузить картинку (моя аватара в нашей локальной сети) в виндовом приложении:
using System.IO;
private void button1_Click(object sender, EventArgs e) {
try {
WebRequest request = WebRequest.Create(@"http://virtuality.bv.du/hc.avatar");
WebResponse response = request.GetResponse();
if (response.ContentType == @"image/jpeg") {
using (Graphics gfx = this.CreateGraphics())
using (Image img = Image.FromStream(response.GetResponseStream())) {
gfx.DrawImage(img, new Point(10, 10));
gfx.Flush();
}
}
} catch (WebException webException) {
MessageBox.Show(webException.Message);
}
}
В вашем случае я порекомендую сделать GenericHandler, который бы загружал картинку с удаленного хоста (и кешировал), а в случае, если ее не окажется (WebException с кодом 404) то выдвал бы какую нибудь дефолтную картинку.
На VB.NET для сайта это выглядит приблизительно вот так:
wrPCRequest = WebRequest.Create("http://www.yyy.m/images/IconsCatalog/" & .Item("Code").ToString.Trim & ".jpg")
Dim wrResponse As WebResponse
wrResponse = wrRequest.GetResponse()
Отказался от этого так как все равно на каком то этапе получаю time out от сервера, но все равно спасибо, так как начал разбиратся с System.Net
В вашем случае я порекомендую сделать GenericHandler, который бы загружал картинку с удаленного хоста (и кешировал), а в случае, если ее не окажется (WebException с кодом 404) то выдвал бы какую нибудь дефолтную картинку.
Если не тяжело - можно пример?
Все таки возникла необходимость довести это до ума.
Можно поступить двумя способами:
1) в ходе рендеринга страницы делаем пробный реквест на удаленный сервер, если получили корректный отклик, то помещаем ссылку на страницу. Это просто, но есть очевидные минусы: повышение времени генерирования страницы (WebRequest штука медленная), повышение нагрузки на удаленный сервер (картинку оттуда требовать будет наш сервер и наш клиент), если подобных страниц достаточно моного, то будет сложнее сопровождать их в дальнейшем (вдруг понадобится таскать картинки из нашей БД или вообще генерировать ее динамически? ). Кароче не круто.
2) делаем специальный проски для картинок - звучит жестоко. На самом деле все просто. .NET позволяет создавать собственные http обработчики - GenericHandler'ы, для этого нужно создать класс, реализующий интерфейс System.Web.IHttpHandler, у него всего один метод (ProcessRequest) и свойство (Reusable). Этот обработчк будет пытаться лезть на удалееный сервер за картинкой, если это удалось, он ее кеширует а также формирует ответ - эту же самую картинку, в противном случае (удаленный сервер не ответил, или поздравил с 4 апреля - ошибка 404) берет картинку из файла. Вот код:
using System.Data;
using System.Configuration;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Caching;
public class ImageProxy : IHttpHandler {
private static string RemoteImageDirectory = @"http://www.remotehost.com/pictures/";
private static string DefaultImageFile = @"~/images/default.jpg";
private static TimeSpan CacheDuration = new TimeSpan(0, 5, 0); // 5 minutes
private static int MaxCachableImageSize = 51200; // 50 kbytes
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = @"image/jpeg";
byte[] imageBuffer = null;
string image = (context.Request.Params["img"] ?? "");
if (image != "") {
imageBuffer = GetRemoteImage(context, image);
} else {
imageBuffer = GetDefaultImage(context);
}
context.Response.BinaryWrite(imageBuffer);
}
private byte[] GetDefaultImage(HttpContext context) {
FileInfo defaultImage = new FileInfo(context.Server.MapPath(DefaultImageFile));
using (FileStream stream = defaultImage.OpenRead()) {
byte[] imageBuffer = new byte[defaultImage.Length];
stream.Read(imageBuffer, 0, imageBuffer.Length);
return imageBuffer;
}
}
private void CacheRemoteImage(HttpContext context, string remoteImageUrl, byte[] image) {
if(image.Length < MaxCachableImageSize)
context.Cache.Add(remoteImageUrl, image, null, DateTime.Now + CacheDuration, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
}
private byte[] GetRemoteImage(HttpContext context, string imageName) {
byte[] imageBuffer = null;
string remoteImageUrl = RemoteImageDirectory + imageName;
object cachedImage = context.Cache[remoteImageUrl];
if (cachedImage != null) {
imageBuffer = (byte[]) cachedImage;
} else {
try {
WebRequest request = WebRequest.Create(remoteImageUrl);
WebResponse response = request.GetResponse();
if (response.ContentType == @"image/jpeg") {
using (Stream stream = response.GetResponseStream()) {
imageBuffer = new byte[response.ContentLength];
stream.Read(imageBuffer, 0, imageBuffer.Length);
}
} else {
imageBuffer = GetDefaultImage(context);
}
} catch {
imageBuffer = GetDefaultImage(context);
}
CacheRemoteImage(context, remoteImageUrl, imageBuffer);
}
return imageBuffer;
}
public bool IsReusable {
get {
return true;
}
}
}
Для того, чтобы ASP.NET знал о нашем http-обработчике, нужно в web.config дописать парочку заклинаний:
<httpHandlers>
<add type="ImageProxy" verb="GET" path="imageproxy"/>
</httpHandlers>
</system.web>
Т.о. мы определили, что ASP.NET будет передавать управление классу ImageProxy для урлов типа:
http://www.myhost.com/imageproxy?img=remoteimage.jpg
Генерировать img тег можно вот так:
З.Ы. Для поддержки http-обработчика со стороны IISv6 (он, сцуко, на web.config не смотрит) нужно лезть в его настройки, о том как его настроить хорошо в MSDN написано было.
:-)
З.Ы. Для поддержки http-обработчика со стороны IISv6 (он, сцуко, на web.config не смотрит) нужно лезть в его настройки, о том как его настроить хорошо в MSDN написано было.
Вот просвещаюсь... :
http://msdn2.microsoft.com/en-us/library/bb515343(vs.90).aspx
Так сказать для последующих покалений... ;-)
Также прочитал книжку.
Вроде все понятно.
Начал делать и сразу уперся в тупик.
Смешно сказать - но на строчку
Inherits IHttpHandler
Ругается, что нет такой вещи.
Раз десять посмотрел что у меня есть:
Imports System.Web
Версия фрайворка 2.xxxxxxxxxxx
Плиз подскажите на какие я грабли наступил?
...со стороны IISv6 ...
Простите за наглость, но не совсем понятно, а на IIS 5.1 (читай WinXP) перехватчик событий не будет работать?
Также прочитал книжку.
Вроде все понятно.
Начал делать и сразу уперся в тупик.
Смешно сказать - но на строчку
Inherits IHttpHandler
Ругается, что нет такой вещи.
Раз десять посмотрел что у меня есть:
Imports System.Web
Версия фрайворка 2.xxxxxxxxxxx
Плиз подскажите на какие я грабли наступил?
Кажется грабли очень простые.
Нужно было только сделать файл: ImageProxy.ashx с помощью VS 2005(и почему этому не пишут в книжках!) который почти все и прописал за меня. Я добавил код hardcase'а и вроде все компильнулось.
Но конечно при запуске приложения с IIS 5.1 IE сразу начал ругатся что не знает такой тип(<add type="ImageProxy" verb="GET" path="imageproxy"/>).
Ставить на рабочий комп винду 2003 с IIS 6.0 у меня нет возможности, то есть придется обойтись без этого. Хотя все равно огромное спасибо hardcase'у - я приобрел еще капельку опыта! :-)
А по поводу IHttpHandler, он железно в System.Web определен и доступен во всех версиях Fw.
Кстати полезен IHttpAsyncHandler - это для асинхронных обработчиков (когда клиентов СЛИШКОМ много и 24 потока тред-пула не справляются).
Добавил позже (или позжее): пока нет возможности IIS 5.1 помучать (дома на машине серверная винда) а на работе (занимаюсь там далеко не ASP.NET) мне админ может рога посбивать за такие вольности.
Значит будем ждать апдейта до 6.0 на рядовой винде...
Еще раз спасибо!
Тогда никто ругаться не будет, а для показа картинок нужно будет использовать
<img src="~/ImageProxy.ashx?img=put_filename_here.img" />
Если конечно ты ashx файл так назвал. (днем голова работат лучше, чем в 2 часа ночи =)) )
Именно то что хотел! Еще раз огромное спасибо.
Но все же, все класс работает, НО картинка режется.
Можно посмотреть тут:
http://www.cdw.co.il/Default.aspx
Или картиночку, есть варианты почему это так?
Просмотрел код ничего не могу найти. Плиз подскажи где грабли?
Жаль, почти сделал, но после без успешных поисков бага который режет картинки пришлось отказаться. Код на VB.NET выложил может кто-нибудь после меня захочет сделать.
Всем спасибо, особенно – hardcase’у
Public Class ImageProxy : Implements IHttpHandler
Private Shared RemoteImageDirectory As String = "http://www.xxx.com/"
Private Shared DefaultImageFile As String
Private Shared CacheDuration As TimeSpan = New TimeSpan(0, 1, 0) ' 1 minutes
Private Shared MaxCachableImageSize As Integer = 51200
'--------------------------------------------------------------------------------------------------------
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
'--------------------------------------------------------------------------------------------------------
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.ContentType = "image/jpeg"
Dim imageBuffer() As Byte = Nothing
Dim image As String
image = context.Request.Params("img")
DefaultImageFile = context.Request.Params("def")
If (image <> "") Then
imageBuffer = GetRemoteImage(context, image)
Else
imageBuffer = GetDefaultImage(context)
End If
context.Response.BinaryWrite(imageBuffer)
End Sub
'--------------------------------------------------------------------------------------------------------
Private Function GetDefaultImage(ByVal context As HttpContext) As Byte()
Dim defaultImage As FileInfo = New FileInfo(context.Server.MapPath(DefaultImageFile))
Dim stream As FileStream = defaultImage.OpenRead
Dim imageBuffer() As Byte = New Byte((defaultImage.Length) - 1) {}
stream.Read(imageBuffer, 0, imageBuffer.Length)
Return imageBuffer
End Function
'--------------------------------------------------------------------------------------------------------
Private Sub CacheRemoteImage(ByVal context As HttpContext, ByVal remoteImageUrl As String, ByVal image() As Byte)
If (image.Length < MaxCachableImageSize) Then
context.Cache.Add(remoteImageUrl, image, Nothing, (DateTime.Now + CacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.Default, Nothing)
End If
End Sub
'--------------------------------------------------------------------------------------------------------
Private Function GetRemoteImage(ByVal context As HttpContext, ByVal imageName As String) As Byte()
Dim imageBuffer() As Byte = Nothing
Dim remoteImageUrl As String = (RemoteImageDirectory + imageName)
Dim cachedImage As Object = context.Cache(remoteImageUrl)
If (Not (cachedImage) Is Nothing) Then
imageBuffer = CType(cachedImage, Byte())
Else
Try
Dim request As WebRequest = WebRequest.Create(remoteImageUrl)
Dim response As WebResponse = request.GetResponse
If (response.ContentType = "image/jpeg") Then
Dim stream As Stream = response.GetResponseStream
imageBuffer = New Byte((response.ContentLength) - 1) {}
stream.Read(imageBuffer, 0, imageBuffer.Length)
Else
imageBuffer = GetDefaultImage(context)
End If
Catch ex As System.Exception
imageBuffer = GetDefaultImage(context)
End Try
CacheRemoteImage(context, remoteImageUrl, imageBuffer)
End If
Return imageBuffer
End Function
End Class
Пока смотрел код нашел пару недочетов - response и stream в GetRemoteImage нужно закрывать:
Dim request As WebRequest = WebRequest.Create(remoteImageUrl)
Dim response As WebResponse = request.GetResponse
Try
If (response.ContentType = "image/jpeg") Then
Dim stream As Stream = response.GetResponseStream
Try
imageBuffer = New Byte((response.ContentLength) - 1) {}
stream.Read(imageBuffer, 0, imageBuffer.Length)
Finally
[COLOR="Red"]stream.Close[/COLOR]
End
Else
imageBuffer = GetDefaultImage(context)
End If
Finally
[COLOR="Red"]response.Close[/COLOR]
End
Catch ex As System.Exception
imageBuffer = GetDefaultImage(context)
End Try
Вот код:
Public Class ImageProxy : Implements IHttpHandler
Private Shared RemoteImageDirectory As String = "http://www.xxx.com"
Private Shared DefaultImageFile As String = "img/NoPict/130X130.gif"
Private Shared CacheDuration As TimeSpan = New TimeSpan(0, 10, 0) ' 10 minutes
Private Shared MaxCachableImageSize As Integer = 51200 * 100
'--------------------------------------------------------------------------------------------------------
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
'--------------------------------------------------------------------------------------------------------
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.ContentType = "image/jpeg"
Dim imageBuffer() As Byte = Nothing
Dim image As String
image = context.Request.Params("img")
If (image <> "") Then
imageBuffer = GetRemoteImage(context, image)
Else
imageBuffer = GetDefaultImage(context)
End If
context.Response.BinaryWrite(imageBuffer)
End Sub
'--------------------------------------------------------------------------------------------------------
Private Function GetDefaultImage(ByVal context As HttpContext) As Byte()
Dim defaultImage As FileInfo = New FileInfo(context.Server.MapPath(DefaultImageFile))
Dim stream As FileStream = defaultImage.OpenRead
Dim imageBuffer() As Byte = New Byte((defaultImage.Length) - 1) {}
stream.Read(imageBuffer, 0, imageBuffer.Length)
Return imageBuffer
End Function
'--------------------------------------------------------------------------------------------------------
Private Sub CacheRemoteImage(ByVal context As HttpContext, ByVal remoteImageUrl As String, ByVal image() As Byte)
If (image.Length < MaxCachableImageSize) Then
context.Cache.Add(remoteImageUrl, image, Nothing, (DateTime.Now + CacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.Default, Nothing)
End If
End Sub
'--------------------------------------------------------------------------------------------------------
Private Function GetRemoteImage(ByVal context As HttpContext, ByVal imageName As String) As Byte()
Dim imageBuffer() As Byte = Nothing
Dim remoteImageUrl As String = (RemoteImageDirectory + imageName)
Dim cachedImage As Object = context.Cache(remoteImageUrl)
If (Not (cachedImage) Is Nothing) Then
imageBuffer = CType(cachedImage, Byte())
Else
Try
Dim request As WebRequest = WebRequest.Create(remoteImageUrl)
Dim response As WebResponse = request.GetResponse
Try
If (response.ContentType = "image/jpeg") Then
Dim stream As Stream = response.GetResponseStream
Try
imageBuffer = New Byte((response.ContentLength) - 1) {}
stream.Read(imageBuffer, 0, imageBuffer.Length)
Finally
stream.Close()
End Try
Else
imageBuffer = GetDefaultImage(context)
End If
Finally
response.Close()
End Try
Catch ex As System.Exception
imageBuffer = GetDefaultImage(context)
End Try
CacheRemoteImage(context, remoteImageUrl, imageBuffer)
End If
Return imageBuffer
End Function
End Class