Displaying images derived from a byte-array dynamically on a page

GordonB picture GordonB · Apr 30, 2009 · Viewed 7.6k times · Source

I'm calling a webservice that is returning an unknown quantity of images in the form of an a collection of byte arrays. (I can't change this)

I need to display each image on a single aspx webpage.

I'm currently using the Microsoft.Web.GeneratedImage control; http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449 to display the images.

The issue i have is that since the control calls a seperate code file to load the image content, i am using session state to store the bytearray, which i'm not overly happy about.

Here's some code from my test project;

     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

What's the most elegant way of achieving this?

Any input welcome!!!

EDIT: Additional info;

  • The images from the webservice are coming from SQL Reporting Services.
  • The images would generally be changing all the time (no real caching requirement).
  • Images would be user specific.
  • The webservice is only called once per page.
  • I'm actually disposing of the image from session state after the generated image uses it, as the image won't be needed to be viewed again for a while.

Answer

kgiannakakis picture kgiannakakis · May 14, 2009

I suppose that you want to call your web service only once per page request. In fact, it would be good to somehow cache the byte array, so that the web service isn't called again in the case the user momentarily moves away from the page and then comes back. In that case saving the byte array in the session is inevitable. If you didn't use GeneratedImage control, you would still need to save the byte array somewhere.

I understand your worries regarding big sessions. Based on the details of your applications, there are some things you could do to avoid it. Are all images refer to a single user, or are some images shared among users? Do the images change often? If all the images belong to a single user and change frequently, then saving them in the session is the only solution. If however some users share images or the images aren't expected to frequently change, then you could create a proxy between the web service and the web application. The proxy will save the images, either in memory or in a database (or perhaps in the file system) and will make them available as resources, through a URL mapping. You would need to define this mapping, based on the internals of your applications. It could be something like this:

http://imageproxy/username/photo123123

You also need to create a URL to return the number of available images:

http://imageproxy/username/imagecount

There would be no need to use the GeneratedImage component. You could easily build the html source of the page using standard img tags.