2012-03-08 24 views
10

Estoy intentando generar un .pdf desde html utilizando la biblioteca ITextSharp. Soy capaz de crear el pdf con el texto HTML convierte en texto pdf/párrafosITextSharp Análisis de HTML con imágenes en él: Analiza correctamente pero no muestra imágenes

mi problema: El pdf no muestra mis imágenes (mi img elementos de la html). Todos mis elementos img html en mi html no se muestran en el pdf? Es posible que ITextSharp analice las imágenes de visualización HTML &. Realmente espero lo contrario estoy rellenas :(

estoy que une al directorio correcto donde las imágenes son (utilizando IMG_BASURL) pero simplemente no se muestran

Mi código:

// mainContents variable is a string containing my HTML 
var document = new Document(PageSize.A4, 50, 50, 80, 100); 
var output = new MemoryStream(); 
var writer = PdfWriter.GetInstance(document, output); 
document.open(); 

Hashtable providers = new Hashtable(); 
providers.Add("img_baseurl","C:/users/xx/VisualStudio/Projects/myproject/"); 
var parsedHtmlElements = HTMLWorker.ParseToList(new StringReader(mainContents), null, providers); 
foreach (var htmlElement in parsedHtmlElements) 
    document.Add(htmlElement as IElement); 

document.Close(); 

Respuesta

11

Cada Ahora que me he encontrado con este problema, la imagen era demasiado grande para el lienzo. Más específicamente, incluso una etiqueta IMG desnuda internamente quedaría envuelta en un Chunk que quedaría envuelto en un Paragraph, y creo que la imagen es desbordando el Párrafo pero no estoy 100% seguro.

Las dos soluciones fáciles son ampliar el lienzo o especificar las dimensiones de la imagen en la etiqueta HTML IMG. La tercera ruta más compleja sería usar un proveedor adicional IMG_PROVIDER. Para hacer esto, debe implementar la interfaz IImageProvider. A continuación se muestra una versión muy simple de un solo

public class ImageThing : IImageProvider { 
     //Store a reference to the main document so that we can access the page size and margins 
     private Document MainDoc; 
     //Constructor 
     public ImageThing(Document doc) { 
      this.MainDoc = doc; 
     } 
     Image IImageProvider.GetImage(string src, IDictionary<string, string> attrs, ChainedProperties chain, IDocListener doc) { 
      //Prepend the src tag with our path. NOTE, when using HTMLWorker.IMG_PROVIDER, HTMLWorker.IMG_BASEURL gets ignored unless you choose to implement it on your own 
      src = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + src; 
      //Get the image. NOTE, this will attempt to download/copy the image, you'd really want to sanity check here 
      Image img = Image.GetInstance(src); 
      //Make sure we got something 
      if (img == null) return null; 
      //Determine the usable area of the canvas. NOTE, this doesn't take into account the current "cursor" position so this might create a new blank page just for the image 
      float usableW = this.MainDoc.PageSize.Width - (this.MainDoc.LeftMargin + this.MainDoc.RightMargin); 
      float usableH = this.MainDoc.PageSize.Height - (this.MainDoc.TopMargin + this.MainDoc.BottomMargin); 
      //If the downloaded image is bigger than either width and/or height then shrink it 
      if (img.Width > usableW || img.Height > usableH) { 
       img.ScaleToFit(usableW, usableH); 
      } 
      //return our image 
      return img; 
     } 
    } 

Para utilizar este proveedor sólo tiene que añadir a la colección proveedor igual que lo hizo con HTMLWorker.IMG_BASEURL:

providers.Add(HTMLWorker.IMG_PROVIDER, new ImageThing(doc)); 

Debe tenerse en cuenta que si utiliza HTMLWorker.IMG_PROVIDER que son responsables de descifrar todo sobre la imagen. El código anterior asume que todas las rutas de las imágenes deben ir precedidas de una cadena constante; es probable que desee actualizar esto y verificar el HTTP al inicio. Además, como decimos que queremos manejar por completo el proceso de procesamiento de imágenes, el proveedor HTMLWorker.IMG_BASEURL ya no es necesario.

El bucle principal código podría ahora ser algo como esto:

 string html = @"<img src=""Untitled-1.png"" />"; 
     string outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "HtmlTest.pdf"); 
     using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) { 
      using (Document doc = new Document(PageSize.A4, 50, 50, 80, 100)) { 
       using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) { 
        doc.Open(); 
        using (StringReader sr = new StringReader(html)) { 
         System.Collections.Generic.Dictionary<string, object> providers = new System.Collections.Generic.Dictionary<string, object>(); 
         providers.Add(HTMLWorker.IMG_PROVIDER, new ImageThing(doc)); 

         var parsedHtmlElements = HTMLWorker.ParseToList(sr, null, providers); 
         foreach (var htmlElement in parsedHtmlElements) { 
          doc.Add(htmlElement as IElement); 
         } 
        } 
        doc.Close(); 
       } 
      } 
     } 

Una última cosa, asegúrese de especificar qué versión de iTextSharp está apuntan a la hora de escribir aquí. El código anterior se dirige a iTextSharp 5.1.2.0, pero creo que podría estar utilizando la serie 4.X.

+0

Estoy tratando de crear y utilizar una clase que implementa IImageProvider basado en el código, pero no está funcionando y creo que tiene algo que ver con esta línea: proveedores.Add (HTMLWorker.IMG_PROVIDER, nueva ImageThing (doc)); Estoy codificando en C# y no puedo usar la enumeración HTMLWorker.IMG_PROVIDER cuando agrego a mi hashtable. ¿Importa si este valor es simplemente una cadena? También quizás necesite hacer algo más desde dentro del ciclo para ejecutar realmente el código GetImage de la clase ImageProvider. Estoy usando itextsharp 4.1.6, en caso de que eso importe. – Neitherman

+0

@Neitherman, publique una nueva pregunta con lo que intentó y lo que no funcionó, haciendo referencia a esta publicación si tiene sentido. –

+0

Nueva pregunta publicada: http://stackoverflow.com/questions/21684040/imageprovider-not-working-in-html-to-pdf-conversion – Neitherman

-1
string siteUrl = HttpContext.Current.Server.MapPath("/images/image/ticket/Ticket.jpg"); 
string HTML = "<table><tr><td><u>asdasdsadasdsa <img src='" + siteUrl + "' al='tt' /> </u></td></tr></table>"; 
+0

Sería bueno saber cómo o por qué funciona esto, si es así ... y creo que esto no funcionaría con la versión actual de iTextSharp ya que la etiqueta

no es compatible. – azarc3

+0

Acabo de hacer esto y aunque el comentario inicial de @GuruRaja no funcionará en la versión actual de iTextSharp. Sin embargo, funcionará si elimina las etiquetas de contenedor

, y
Y utiliza una URL como origen de la imagen (no una ruta física del servidor). – azarc3

2

que enfrentan el mismo problema y trataron las siguientes soluciones propuestas: cadena reemplazado una etiqueta, codificación en base 64 e incrustar la imagen a una biblioteca de clases de .NET pero ninguno funcionó! Así que he llegado a la solución pasada de moda: añadir el logotipo de forma manual con doc.Add()
Aquí está actualizado su código:

string html = @"<img src=""Untitled-1.png"" />"; 
     string outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "HtmlTest.pdf"); 
     using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) { 
      using (Document doc = new Document(PageSize.A4, 50, 50, 80, 100)) { 
       using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) { 
        doc.Open(); 
        using (StringReader sr = new StringReader(html)) { 
         System.Collections.Generic.Dictionary<string, object> providers = new System.Collections.Generic.Dictionary<string, object>(); 
         providers.Add(HTMLWorker.IMG_PROVIDER, new ImageThing(doc)); 

         var parsedHtmlElements = HTMLWorker.ParseToList(sr, null, providers); 
         foreach (var htmlElement in parsedHtmlElements) { 
          doc.Add(htmlElement as IElement); 
         } 
// here's the magic 
var logo = iTextSharp.text.Image.GetInstance(Server.MapPath("~/HTMLTemplate/logo.png")); 
       logo.SetAbsolutePosition(440, 800); 
       document.Add(logo); 
// end 
        } 
        doc.Close(); 
       } 
      } 
     } 
+0

Para ahorrarle tiempo a alguien, no necesita la ruta server.map. Puede usar una ruta de archivo si no está usando una aplicación web. –

Cuestiones relacionadas