【问题标题】:ITextSharp Parsing HTML with Images in it: It parses correctly but wont show imagesITextSharp解析带有图像的HTML:它解析正确但不会显示图像
【发布时间】:2012-03-25 13:47:16
【问题描述】:

我正在尝试使用库 ITextSharp 从 html 生成 .pdf。我能够创建将 html 文本转换为 pdf 文本/段落的 pdf

我的问题: pdf 不显示我的图像(我的 img 来自 html 的元素)。我的 html 中的所有 img html 元素都没有显示在 pdf 中? ITextSharp 是否可以解析 HTML 和显示图像。我真的希望如此,否则我会被塞满:(

我正在链接到图像所在的正确目录(使用 IMG_BASURL),但它们只是没有显示

我的代码:

// 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();

【问题讨论】:

    标签: c# asp.net itextsharp


    【解决方案1】:

    我遇到了同样的问题并尝试了以下建议的解决方案: string 替换了一个标签,在 base64 中编码并将图像嵌入到 .NET 类库中,但没有一个工作! 所以我采用了老式的解决方案:使用doc.Add()手动添加徽标
    这是您的代码更新:

    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();
                    }
                }
            }
    

    【讨论】:

    • 为了节省时间,您不需要 server.map 路径。如果您不使用网络应用程序,则可以使用文件路径。
    【解决方案2】:
    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>";
    

    【讨论】:

    • 很高兴知道它是如何工作或为什么工作的,如果它确实如此......我相信这不适用于当前版本的 iTextSharp,因为不支持 标签。
    • 刚刚开始工作,尽管@GuruRaja 的初始评论在当前版本的 iTextSharp 中不起作用。但是,如果您删除
    • 、 和
      容器标签并使用 URL 作为图像源(而不是物理服务器路径),它将起作用。
    【解决方案3】:

    每次我遇到这个问题都是图像对于画布来说太大了。更具体地说,即使是赤裸裸的 IMG 标签内部也会被包裹在 Chunk 中,而 Paragraph 会被包裹在 Paragraph 中,我认为图像溢出了段落,但我不是 100% 确定。

    两个简单的修复方法是放大画布或在 HTML IMG 标记上指定图像尺寸。第三个更复杂的途径是使用额外的提供者IMG_PROVIDER。为此,您需要实现IImageProvider 接口。下面是一个非常简单的版本

        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;
            }
        }
    

    要使用此提供程序,只需像使用 HTMLWorker.IMG_BASEURL 一样将其添加到提供程序集合中:

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

    需要注意的是,如果您使用HTMLWorker.IMG_PROVIDER,您有责任搞清楚有关图像的所有内容。上面的代码假定所有图像路径都需要在前面加上一个常量字符串,您可能需要更新它并在开始时检查HTTP。此外,因为我们说我们想要完全处理图像处理管道,所以不再需要提供程序 HTMLWorker.IMG_BASEURL

    主代码循环现在看起来像这样:

            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();
                    }
                }
            }
    

    最后一件事,请确保在此处发布时指定您所针对的 iTextSharp 版本。上面的代码针对 iTextSharp 5.1.2.0,但我认为您可能使用的是 4.X 系列。

    【讨论】:

    • 我正在尝试创建和使用基于此代码实现 IImageProvider 的类,但它不起作用,我相信它与这一行有关:providers.Add(HTMLWorker.IMG_PROVIDER, new图像事物(文档));我正在用 C# 编码,当我添加到我的哈希表时,我无法使用 HTMLWorker.IMG_PROVIDER 枚举。这个值是否只是一个字符串?另外,也许我需要在循环内部做一些事情来实际执行 ImageProvider 类中的 GetImage 代码。我正在使用 itextsharp 4.1.6,以防万一。
    • @Neitherman,请发布一个新问题,说明您尝试过的方法和无效的方法,如果有意义,请参考这篇文章。
    • IImageProvider 自 5.5.2 起已弃用 (api.itextpdf.com/itext/com/itextpdf/text/html/simpleparser/…)
    • HTMLWorker 本身已被弃用,而不仅仅是那个类。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签