Exibindo imagens derivadas de uma forma dinâmica byte-array em uma página
Pergunta
Eu estou chamando um webservice que está retornando uma quantidade desconhecida de imagens na forma de uma coleção de matrizes de bytes. (Eu não posso mudar isso)
Eu preciso para exibir cada imagem em uma única página aspx.
Atualmente estou usando o controle Microsoft.Web.GeneratedImage; http://www.codeplex.com/aspnet/Release/ProjectReleases. aspx? ReleaseId = 16449 para exibir as imagens.
O problema que tenho é que, desde o controle chama um arquivo de código separado para carregar o conteúdo da imagem, eu estou usando o estado da sessão para armazenar o bytearray, que eu não sou demasiado feliz.
Aqui está algum código do meu projeto de teste;
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
O que é a maneira mais elegante de conseguir isso?
Qualquer entrada de boas-vindas !!!
EDIT: Informações adicionais;
- As imagens do webservice são vindo do SQL Reporting Services.
- As imagens geralmente seria mudando o tempo todo (não real exigência de caching).
- Imagens seria específico de usuário.
- O webservice é chamado apenas uma vez por página.
- Na verdade, estou a eliminação da imagem da o estado da sessão após o gerado imagem usa-lo, como a imagem não será necessário para ser visto novamente por um enquanto.
Solução
Você pode incorporar os dados da imagem diretamente no código fonte da página usando o esquema URI data:
. Aqui está a descrição Wikipedia . Isso não funciona com versões do IE anteriores a 8, porém, o que pode torná-lo inaceitável para a sua situação.
Outras dicas
Eu suponho que você quer chamar o serviço web apenas uma vez por solicitação de página. Na verdade, seria bom para alguma forma armazenar em cache a matriz de bytes, para que o serviço web não é chamado novamente no caso do usuário momentaneamente se move para fora da página e depois volta. Nesse caso salvar o array de bytes na sessão é inevitável. Se você não usar o controle GeneratedImage, você ainda precisa para salvar a algum lugar matriz de bytes.
Eu entendo suas preocupações em relação a sessões grandes. Com base nos detalhes de suas aplicações, existem algumas coisas que você pode fazer para evitá-lo. São todas as imagens se referem a um único usuário, ou estão algumas imagens compartilhadas entre os usuários? Será que as imagens mudam frequentemente? Se todas as imagens pertencem a um único usuário e mudam com freqüência, em seguida, salvá-los na sessão é a única solução. Se, no entanto alguns usuários compartilhar imagens ou as imagens não se espera que mudam frequentemente, então você pode criar um proxy entre o serviço web ea aplicação web. O proxy irá salvar as imagens, seja na memória ou em um banco de dados (ou talvez no sistema de arquivos) e irá disponibilizá-los como recursos, através de um mapeamento de URL. Você precisará definir esse mapeamento, baseado nas partes internas de suas aplicações. Poderia ser algo como isto:
http://imageproxy/username/photo123123
Você também precisa criar um URL para retornar o número de imagens disponíveis:
http://imageproxy/username/imagecount
Não haveria necessidade de usar o componente GeneratedImage. Você poderia facilmente construir o código HTML da página usando tags img padrão.
No asp.net, você pode escrever e imagem diretamente com o objeto de resposta e os principais navegadores será capaz de exibi-lo. Mas você não pode passar um array de bytes, você precisa passar um fluxo de memória.
obter o seu System.Web.HttpContext
Dim ms as New Io.MemoryStream(yourarray)
httpcontext.Response.OutputStream.Write(ms.ToArray,0,ms.Length)
você colocar isso em uma página display.aspx e se "yourarray" é um array de bytes que representa uma imagem o navegador irá exibi-lo.
Você pode usar, em seguida, um controle de imagem em qualquer página (mesmo html simples) e definir a fonte de imagem para "display.aspx" e sua imagem vai aparecer.
Agora, desde que você tem várias imagens, pode ser necessário criar um controle e criar várias instâncias do mesmo, um para cada imagem passando a matriz byte correspondente.