Sirviendo imágenes mediante ActionResult en MVC.

Hola, antes de empezar, desearles a todos un feliz inicio de año y que el trabajo que realicen le haga posible hacer realidad todas las metas que se han trazado.

En el post de hoy vamos a ver cómo podemos servir imágenes mediante un ActionResult en MVC. La práctica de este mecanismo puede ser aplicado a servir imágenes desde una base de datos hacia nuestra WEB o, modificar una imagen que tengamos en el sistema de archivos antes de servirla a nuestra WEB.

No hay truco alguno en esto, simplemente se trata de implementar un nuevo ActionResult que cargue la imagen desde donde queremos y luego la sirva al cliente como un arreglo de byte indicando que el contexto del resultado es del tipo Imagen.

Vamos allá…

Empezamos con el ejemplo más simple. Saquemos la imagen de la base de datos y la servimos a la WEB.

public class PhotoResult : ActionResult
{
  
public override void ExecuteResult(ControllerContext context)
  
{
     
var id = context.HttpContext.Request.QueryString[«id»]; 

     using (var uow = new UnitOfWork())
    
{
        
var photoBytes = (new CustomersDAC(uow).Load(id)).Photo.ToArray();
    
} 

     context.HttpContext.Response.ContentType = «image/png»;
    
context.HttpContext.Response.BinaryWrite(buffer);

    
context.HttpContext.Response.Flush();
 
}
}

Sencillo, implementamos una clase que herede de ActionResult y sobre-escribimos el método ExecuteResult. En este método tomamos un parámetro “id” que nos enviarán por el QueryString y traemos de la base de datos una imagen que tenemos almacenada en forma de arreglo de bytes.

Cuando tenemos el arreglo de bytes lo escribimos en la respuesta que se envía al cliente e indicamos que el tipo de contenido es imagen y su formato es png.

Hasta aquí ya tenemos el ActionResult, ahora solo necesitamos un método en el controlador que nos retorne una instancia de PhotoResult.

public PhotoResult GetPhotoByCustomer()
{
  
return new PhotoResult();

}

Nada más… esto es todo lo que necesitamos para que el controlador ejecute nuestra acción y retorne la imagen al cliente. ¿Cómo lo invocamos?

<img alt=»Your Photo» src<%= Url.Action(«GetPhotoByCustomer?id=1», «Home») %>« />

Cuando el browser hace el GET al servidor para obtener el src de la imagen, en nuestra aplicación esto será traducido a un Request al Método que tenemos dentro del controlador, el cual se encargará de retornarnos la imagen solicitada.

Otra aplicación que mencionamos al inicio del post y que puede tener esta manera de servir imágenes al cliente es cuando queremos modificar una imagen que ya tenemos almacenada en el sistema de archivos antes de mostrarla.

Imaginemos que tenemos una imagen a la cual queremos insertarle un copyright en el momento en que se sirva al cliente y de esta forma ahorrarnos tener que estar editando todas las imágenes que vamos a utilizar antes de subir al servidor.

El cambio para poder hacer lo anterior está solo en el ActionResult que implementamos. El resto de la implementación es exactamente igual.

public class CopyrightImageResult : ActionResult
{
  
private const string Copyright = «Copyright (c) Omar del Valle Rodríguez»; 

   public override void ExecuteResult(ControllerContext context)
  
{
     
var imagePath = context.HttpContext.Server.MapPath(«/images/Photo.PNG»);
     
var mainImage = Image.FromFile(imagePath);
     
var memStream = new MemoryStream(); 

      var fontCopyright = new Font(«Arial», 12);
     
const float xCopyrightPoint = 493.0f;
     
const float yCopyrightPoint = 70.0f; 

      //create graphics from main image
     
using (var g = Graphics.FromImage(mainImage))
     
{
        
g.DrawString(Copyright, fontCopyright, Brushes.Black, xCopyrightPoint, yCopyrightPoint);
        
mainImage.Save(memStream, ImageFormat.Png);
     
} 

      var buffer = memStream.ToArray(); 

      context.HttpContext.Response.ContentType = «image/png»;
     
context.HttpContext.Response.BinaryWrite(buffer);
     
context.HttpContext.Response.Flush();
  
}
}

Lo dicho, cargamos la imagen del sistema de archivos y dibujamos en ella lo que deseamos. Salvamos el resultado a un MemoryStream y lo retornamos como un arreglo de bytes al cliente.

Salu2 y hasta la próxima…