[Tip/Trick] ASP.NET MVC & PDF

Uno de las preguntas que se suele encontrar en los foros MSDN  es como mostrar un fichero PDF desde ASP.NET y como últimamente he estado trabajando con MVC y me parece muy interesante voy a mostrar como se puede hacer esto desde el controlador.

Normalmente podemos optar por dos estratégicas a la hora de mostrar un documento PDF.

1. Mostrar un fichero

Si tenemos un fichero pdf que queremos mostrar crearemos un controlador que se encargue de mostrar este recurso.

 

pdf2

Con MVC tenemos un método del controlador que nos facilita muchísimo el trabajo File que se encarga de enviar el contenido de un fichero binario a la respuesta y solo tenemos que indicar el tipo “contentType” para que se muestra correctamente.

public ActionResult GetPDF()
{
  string filename = @"~Contentjquery.cheatsheet.1.4.pdf";
  return File(filename, "application/pdf", 
                 Server.HtmlEncode(filename));
}

De esta manera podemos mostrar ficheros pdf, exel, word, etc. De una manera facilísima.

pdf1

2. Generar un documento Pdf al vuelo

Para poder mostrar el documento pdf correctamente tendemos que utilizar alguna de las librerías gratuitas que existen en la red y en este ejemplo yo he optado por itextSharp.

pdf3

Crearemos otra acción que generará un documento pdf dinámicamente, de esta manera podremos elegir crear el documento enteramente nosotros por código o utilizar una vista como plantilla para el documento.

Yo he creado una vista parcial “userControl” para generar el documento.

pdf6 pdf4

Describiré un poco el código de esta Acción:

  1:  public ActionResult PDF()
  2:  {    
  3:    ControllerContext context = this.ControllerContext;
  4:    string partialViewName = "PDF";
  5:         
  6:    byte[] buf = null;
  7:    MemoryStream pdfTemp = new MemoryStream();
  8:    ViewEngineResult result = ViewEngines.Engines.FindPartialView(context,
  9:                                 partialViewName);
 10: 
 11:    if (result.View != null)
 12:    {
 13:       string htmlTextView = GetViewToString(context, result);
 14:       iTextSharp.text.Document doc = new iTextSharp.text.Document();
 15:       iTextSharp.text.pdf.PdfWriter writer = 
 16:       iTextSharp.text.pdf.PdfWriter.GetInstance(doc, pdfTemp);
 17:       writer.CloseStream = false;
 18:       doc.Open();
 19:       doc.Add(new iTextSharp.text.Paragraph("Documento PDF al Vuelo"));
 20:       AddHTMLText(doc, htmlTextView);
 21:       doc.Close();
 22: 
 23:       buf = new byte[pdfTemp.Position];
 24:       pdfTemp.Position = 0;
 25:       pdfTemp.Read(buf, 0, buf.Length);
 26:    }
 27:    return File(buf, "application/pdf", "tempPdf.pdf");
 28:  }

8: obtendremos la vista que queremos utilizar como plantilla para el documento pdf.

13: Obtendremos el contenido HTML de la vista como texto. Para eso utilizaremos el método GetViewToString.

16: Guardaremos el documento en memoria “memoryStream” para volcar el resultado posteriormente en la respuesta.

 private string GetViewToString(ControllerContext context, ViewEngineResult result)
 {
    string viewResult = "";
    ViewDataDictionary viewData = new ViewDataDictionary();
    TempDataDictionary tempData = new TempDataDictionary(); 
    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
       using (HtmlTextWriter output = new HtmlTextWriter(sw))
       {
          ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, output);
          result.View.Render(viewContext, output);
       }
       viewResult = sb.ToString();
    }
    return viewResult;
 }

19: Podemos crear el documento por código.

20: Añadiremos el contenido de la vista al documento como texto HTML utilizando el método AddHTMLText().

private void AddHTMLText(iTextSharp.text.Document doc, string html)
{
   List<iTextSharp.text.IElement> htmlarraylist = HTMLWorker.ParseToList(
                   new StringReader(html), null);                
             
   foreach (var item in htmlarraylist)
   {
      doc.Add(item);
   }
}

27: Finalmente retornaremos el documento generado al vuelo como un fichero guardado en memoria.

pdf5

Espero poder seguir haciendo más prácticas de este estilo con MVC, porque me esta gustando mucho 😉

9 comentarios en “[Tip/Trick] ASP.NET MVC & PDF”

  1. Jejejejeeee… Muy buen post!
    Ya veo que vas abandonar webforms para pasarte de lleno a MVC! 😛

    Tu post me ha dado una idea para otro post que voy a intentar escribir esta tarde o mañana a ver que sale! 😛

    Un saludo!

  2. Hola Marc, muy bueno el post.
    Por favor respondeme si es que podria exportar una pagina asp.net completa a formato PDF con MVC.

    Grcias.

    Saludos Coordiales.

  3. Aún no he tenido tiempo de comenzar con MVC son demasiados cambios en poco tiempo Silverlight,MVC, WWF, Entitys, Linq to Entity, cambios en seguridad en 4.0, cambio de versión en WCF, entiendo que la conversión de XML hacia PDF no es posible sin MVC, yo creo recordar que XSLT tenia una salida hacia PDF ¿no?

  4. Hola disculpe si me podria ayudar con el codigo ya que ami me da problemas al momento de pasarle a un List el resultado del HTMLWorker por fa seria de una gran ayuda

  5. Muy bueno Marc!!

    Ahora, un problema que me estoy encontrando al pasar una vista a PDF.
    Mi vista tiene enlazada una hoja de estilos Pues cuando se crea el PDF, no reconoce los estilos que hay en la pagina enlazada.

    Algo parecido me pasa al poner un background-image:

    A ver si me puedes echar un cable 😉

    Un saludo!!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *