Динамическое отображение изображений, полученных из байтового массива, на странице
Вопрос
Я вызываю веб-сервис, который возвращает неизвестное количество изображений в виде коллекции байтовых массивов.(Я не могу это изменить)
Мне нужно отображать каждое изображение на одной веб-странице aspx.
В настоящее время я использую элемент управления Microsoft.Web.GeneratedImage;http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449для отображения изображений.
Проблема, с которой я столкнулся, заключается в том, что, поскольку элемент управления вызывает отдельный файл кода для загрузки содержимого изображения, я использую состояние сеанса для хранения байтового массива, что меня не очень устраивает.
Вот код из моего тестового проекта;
Private Sub btnGetChart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGetChart.Click
Dim reportHub As New HubWrapper
Dim repCharts() As ReportHub.Chart = reportHub.ReportHubChart(Me.ddlReports.SelectedValue, ViewState("params"))
For Each chart As ReportHub.Chart In repCharts
Dim sessionKey As String = "img" & System.Guid.NewGuid().ToString
Dim imgParam As New Microsoft.Web.ImageParameter()
imgParam.Name = "sessionVar"
imgParam.Value = sessionKey
Session(sessionKey) = chart.ChartData
Dim img As New Microsoft.Web.GeneratedImage
img.ImageHandlerUrl = "~/chartImageHandler.ashx"
img.Parameters.Add(imgParam)
phChart.Controls.Add(img)
Next
End Sub
<%@ WebHandler Language="VB" Class="chartImageHandler" %>
Imports System
Imports System.Collections.Specialized
Imports System.Drawing
Imports System.Web
Imports Microsoft.Web
Public Class chartImageHandler
Inherits ImageHandler
Implements IRequiresSessionState
Public Sub New()
MyBase.New()
'Set caching settings and add image transformations here
'EnableServerCache = True
End Sub
Public Overrides Function GenerateImage(ByVal parameters As NameValueCollection) As ImageInfo
Dim byteArry As Byte() = CType(HttpContext.Current.Session(parameters("sessionVar")), Byte())
HttpContext.Current.Session.Remove(parameters("sessionVar"))
Return New ImageInfo(byteArry)
End Function
End Class
Какой самый элегантный способ добиться этого?
Любой вклад приветствуется!!!
РЕДАКТИРОВАТЬ:Дополнительная информация;
- Изображения из веб -сервиса поступают из SQL Reporting Services.
- Изображения обычно меняются все время (без реального требования к кэшированию).
- Изображения будут зависеть от пользователя.
- Веб-сервис вызывается только один раз на странице.
- Я на самом деле удаляю изображение из состояния сеанса после того, как сгенерированное изображение использует его, так как изображение не нужно будет просмотреть снова на некоторое время.
Решение
Вы можете встроить данные изображения непосредственно в источник страницы, используя data:
Схема URI. Вот описание в Википедии.Однако это не работает с версиями IE до 8, что может сделать это неприемлемым для вашей ситуации.
Другие советы
Я предполагаю, что вы хотите вызывать свой веб-сервис только один раз для каждого запроса страницы.На самом деле, было бы неплохо как-то кэшировать массив байтов, чтобы веб-сервис не вызывался повторно в случае, если пользователь на мгновение уйдет со страницы, а затем вернется.В этом случае сохранение массива байтов в сессии неизбежно.Если вы не использовали элемент управления GeneratedImage, вам все равно нужно будет где-нибудь сохранить массив байтов.
Я понимаю ваше беспокойство по поводу больших сессий.Основываясь на деталях ваших приложений, вы можете сделать несколько вещей, чтобы избежать этого.Все изображения относятся к одному пользователю или некоторые изображения являются общими для всех пользователей?Часто ли меняются изображения?Если все изображения принадлежат одному пользователю и часто меняются, то сохранение их в сеансе — единственное решение.Однако если некоторые пользователи делятся изображениями или изображения не будут часто меняться, вы можете создать прокси-сервер между веб-службой и веб-приложением.Прокси-сервер сохранит изображения либо в памяти, либо в базе данных (или, возможно, в файловой системе) и сделает их доступными в качестве ресурсов посредством сопоставления URL-адресов.Вам нужно будет определить это сопоставление на основе внутреннего устройства ваших приложений.Это может быть что-то вроде этого:
http://imageproxy/username/photo123123
Вам также необходимо создать URL-адрес для возврата количества доступных изображений:
http://imageproxy/username/imagecount
Не будет необходимости использовать компонент GeneratedImage.Вы можете легко создать исходный HTML-код страницы, используя стандартные теги img.
В asp.net вы можете писать и отображать изображения непосредственно с объектом ответа, и основные браузеры смогут его отображать.Но вы не можете передать массив байтов, вам нужно передать поток памяти.
Получите ваш System.Web.HttpContext
Dim ms as New Io.MemoryStream(yourarray)
httpcontext.Response.OutputStream.Write(ms.ToArray,0,ms.Length)
вы помещаете это на страницу display.aspx, и если «ваш массив» представляет собой массив байтов, представляющий изображение, браузер отобразит его.
Затем вы можете использовать элемент управления изображением на любой странице (даже простой HTML) и установить источник изображения «display.aspx», и ваше изображение появится.
Теперь, поскольку у вас есть несколько изображений, вам может потребоваться создать элемент управления и создать несколько его экземпляров, по одному для каждого изображения, передающего соответствующий массив байтов.