Itext7 HtmlConverter不显示gif

Posted

技术标签:

【中文标题】Itext7 HtmlConverter不显示gif【英文标题】:Itext7 HtmlConverter does not display gif 【发布时间】:2021-11-11 14:01:14 【问题描述】:

我正在尝试将 html 转换为具有相对路径的图像标签的 pdf。

<IMG src="./ups_logo.gif" ALT="UPS Logo">

这是我从 API 获得的动态 HTML。

当我像这样使用 HTMLConverter 将其转换为 PDF 时:

string htmlString = "<!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.0 Transitional//EN\"><HTML><HEAD><META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\"><TITLE>UPS Package Tracking</TITLE></HEAD><BODY><TABLE width=500 border=0 cellSpacing=0 cellPadding=0><TR><TD rowspan=\"30\" Width=\"17\">&nbsp;</TD><TD><TABLE cellSpacing=0 cellPadding=0 border=0 ><TR><TD align=\"left\" width=\"30\" > <IMG src=\"./ups_logo.gif\" ALT=\"UPS Logo\"></TD><TD><IMG src=\"./ups_banner.gif\" ALT=\"UPS Banner\" ></TD></TR></TABLE></TD></TR><TR><TD><TABLE cellSpacing=0 cellPadding=0 width=500 border=0 ><TR><TD colSpan=2 align=left><B>DELIVERY NOTIFICATION</B></TD><TD></TD></TR><TR><TD>&nbsp;</TD></TR><TR><TD colSpan=2>Dear Customer,</TD></TR><TR><TD>&nbsp;</TD></TR><TR><TD colSpan=3>This is in response to your request for delivery information concerning the shipment listed below.</TD></TR><TR><TD>&nbsp;</TD></TR><TR><TD align=right>Tracking Number:&nbsp;&nbsp;</TD><TD align=left>XX XXX XXX XX XXXX XXX X</TD></TR><TR><TD valign=top align=right><nobr>&nbsp;&nbsp;&nbsp;Reference Number(s):&nbsp;&nbsp;</nobr></TD><TD align=left><Table cellSpacing=0 cellPadding=0 width = 65%><TR><TD>XXXXXXXXXXXXXXXXX, XXXX, XXXXXXXXXXXXXXXXX, XXXXX5  </TD></TR></TABLE></TD></TR><TR><TD align=right>Service Type:&nbsp;&nbsp;</TD><TD align=left>UPS GROUND</TD></TR><TR><TD align=right>Package Weight:&nbsp;&nbsp;</TD><TD align=left>7.00 LBS</TD></TR><TR><TD align=right>Shipped or Billed on:&nbsp;&nbsp;</TD><TD align=left>Sep 01, 2021</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR><TR><TD align=right valign=top>Delivered on:&nbsp;&nbsp;</TD><TD align=left>Sep 07, 2021 3:10 P.M.</TD></TR><TR><TD align=right valign=top>Delivered to:&nbsp;&nbsp;</TD><TD align=left>York, NY, US, 11111</TD></TR><TR><TD align=right>Signed By:&nbsp;&nbsp;</TD><TD align=left>AngryOtter</TD></TR><TR><TD align=right>Location:&nbsp;&nbsp;</TD><TD align=left>Receiver</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>  <TR><TD colSpan=2>Thank you for giving us this opportunity to serve you.</TD></TR><TR><TD>&nbsp;</TD></TR>  <TR><TD>Sincerely,</TD></TR>  <TR><TD>United Parcel Service</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR><TR><TD colSpan=2>Tracking results provided by UPS: &nbsp;Sep 16, 2021 2:02 P.M. Eastern Time (USA)</TD></TR></TABLE></TD></TR></TABLE></BODY></HTML>";

        byte[] pdfData;
        using (var memoryStream = new MemoryStream())
        
                ConverterProperties properties = new ConverterProperties();
                properties.SetBaseUri("../img/");
                HtmlConverter.ConvertToPdf(htmlString, memoryStream,properties);
                pdfData = memoryStream.ToArray();
        
        File.WriteAllBytes("c:\\test.pdf", pdfData);

其他一切都显示得很好,我生成了 PDF,所有信息都在那里,但图像没有显示。它也没有坏,只是不在那里。也不例外。图片的源文件目前在项目的解决方案级别。

文件结构:

Desktop
  --TrackWSSample
    --.sln
    --.suo
    --img(folder)
      --ups_logo.gif
    --TrackWSSample
      --app.config
      --package.config
      --program.cs

编辑:我的请求/响应代码:

        TrackService track = new TrackService();
        TrackRequest tr = new TrackRequest();
        UPSSecurity upss = new UPSSecurity();

        UPSSecurityServiceAccessToken upssSvcAccessToken = new UPSSecurityServiceAccessToken();
        upssSvcAccessToken.AccessLicenseNumber = "my_number";
        upss.ServiceAccessToken = upssSvcAccessToken;

        UPSSecurityUsernameToken upssUsrNameToken = new UPSSecurityUsernameToken();
        upssUsrNameToken.Username = "userName";
        upssUsrNameToken.Password = "Password";
        upss.UsernameToken = upssUsrNameToken;

        track.UPSSecurityValue = upss;
        RequestType request = new RequestType();
        string[] requestOption =  "14" ;
        request.RequestOption = requestOption;
        tr.Request = request;
        tr.InquiryNumber = "my_tracking_number";
        System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11; //This line will ensure the latest security protocol for consuming the web service call.
        TrackResponse trackResponse = track.ProcessTrack(tr);
        string s = trackResponse.Shipment[0].Package[0].Activity[0].Document[0].Content;
        byte[] htmlBytes = Convert.FromBase64String(s);
        string htmlString = Encoding.UTF8.GetString(htmlBytes);

感谢任何帮助

【问题讨论】:

@KJ 不,我什至硬编码了图像的绝对路径,仍然没有工作 @KJ gif 仍然不存在,即使我将 url 设置为 "./img/"。绝对不需要路径,因为 prod 环境将具有不同的路径。但是,当我做properties.SetBaseUri("C:/Users/User Name/Desktop/TrackWSSample/img"); 时,即使这样也不起作用 能否添加发送/接收请求的代码以便我进行测试?显然,用通用数据替换您的用户名、密码和 AccessLicenseNumber。 (例如:my_username、my_password、my_access_license_number)。 @user9938 添加,和UPS提供的示例代码差别不大。 【参考方案1】:

根据pdfHTML: configuration options:

ConverterProperties: 通过各种方法重载,您可以 在前两个参数中指定某些输入参数类型,但是 总是有可选的第三个参数 ConverterProperties。这 参数包含允许用户使用的基本配置选项 以各种方式自定义输入数据的处理。我们现在将 详细说明这些选项,以便您可以配置您的 pdfHTML 代码 以获得最佳结果。

baseUri:如果 HTML 文件需要任何外部资源,例如 独立的 CSS 文件或图像文件,然后 pdfHTML 文件需要知道 这些在哪里。该位置可能是 本地文件系统或在线。

pdfHTML 将尝试使用合理的默认值,以防您不这样做 指定一个 baseUri。如果您使用字符串参数来传递您的 HTML, 那么默认值将是执行代码的文件夹。 如果您将 convertToPdf 的重载与 File 参数一起使用,它将 使用与输入文件相同的位置。

如果这些默认设置都不适合您,那么您需要 定义默认资源位置根。然后,在 HTML 文件将从该路径开始查找资源。它是 可以使用 ../ 语法在您的目录树中上 文件系统,但出于其他目的,指定的 URI 充当 用于确定路径的根文件夹。

先决条件

下载/安装 NuGet 包itext7 下载/安装 NuGet 包itext7.pdfhtml

添加以下 using 语句

using System;
using System.IO;
using iText.Html2pdf;

尝试以下方法:

注意:指定 HTML 文件名、PDF 文件名(另存为)和 baseUri(如果 HTML 文件包含图像或样式表等资源)

创建PDF

public static void CreatePdf(string htmlFilename, string pdfFilename, string baseUri = "")

    byte[] pdfData;

    if (!System.IO.File.Exists(htmlFilename))
    
        throw new Exception("Error: '" + htmlFilename + "' doesn't exist.");
    

    using (FileStream fs = new FileStream(htmlFilename, FileMode.Open, FileAccess.Read))
    
        using (var memoryStream = new MemoryStream())
        
            //when specifying HTML as a string and the HTML includes
            //a resource that uses relative paths,
            //it's necessary to specify the baseUri (path)

            //create new instance
            ConverterProperties properties = new ConverterProperties();

            if (!String.IsNullOrEmpty(baseUri))
            
                //set value
                properties.SetBaseUri(baseUri);
            
            else
            
                //get folder name that HTML file exists in
                string folderName = System.IO.Path.GetDirectoryName(htmlFilename);

                //set value
                properties.SetBaseUri(folderName);
            

            //System.Diagnostics.Debug.WriteLine("BaseURI: " + properties.GetBaseUri());

            //convert HTML to PDF
            HtmlConverter.ConvertToPdf(fs, memoryStream, properties);

            //save to byte[]
            pdfData = memoryStream.ToArray();
        
    

    File.WriteAllBytes(pdfFilename, pdfData);


public static void CreatePdfFromHtmlString(string htmlString, string pdfFilename, string baseUri)


    byte[] pdfData;
    using (var memoryStream = new MemoryStream())
    
        //when specifying HTML as a string and the HTML includes
        //a resource that uses relative paths,
        //it's necessary to specify the baseUri (path)

        //create new instance
        ConverterProperties properties = new ConverterProperties();

        //set value
        properties.SetBaseUri(baseUri);

        //convert HTML to PDF
        HtmlConverter.ConvertToPdf(htmlString, memoryStream, properties);

        //save to byte[]
        pdfData = memoryStream.ToArray();
    

    File.WriteAllBytes(pdfFilename, pdfData);

用法:将 HTML 指定为字符串

string htmlFilename = @"C:\Temp\default.html";
string folderName = System.IO.Path.GetDirectoryName(htmlFilename);
string html = System.IO.File.ReadAllText(htmlFilename);
string pdfFilename = @"C:\Temp\default.pdf";

//convert HTML to PDF and save to file
CreatePdfFromHtmlString(html, pdfFilename, folderName);

用法:指定 HTML 文件名

string htmlFilename = @"C:\Temp\default.html";
string pdfFilename = @"C:\Temp\default.pdf";

//convert HTML to PDF and save to file
CreatePdf(htmlFilename, pdfFilename);

更新

以下是用于测试的 HTML 文件:

default.html

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <h2>HTML Test</h2>

        <div>
            <IMG src="./ups_logo.gif" ALT="UPS Logo">
        </div>

        <p>
            <div>
                This is a test message
            </div>
    </body>
</html>

注意:名为“ups_logo.gif”的图像文件应与 HTML 文件位于同一文件夹中。


更新 2

由于您似乎在从文件中获取徽标图像时遇到问题,请使用以下方法将从 UPS Developer Kit 下载的 .zip 文件中的徽标图像转换为 base64 字符串 - 您将在“Common”中找到徽标图像和 .zip 文件中的 General\Logos\LOGO_L.gif"。

ConvertImageToBase64String

private static string ConvertImageToBase64String(string filename)

    string result = string.Empty;

    using (System.Drawing.Image image = System.Drawing.Image.FromFile(filename))
    
        using (System.IO.MemoryStream m = new System.IO.MemoryStream())
        
            image.Save(m, image.RawFormat);
            byte[] imageBytes = m.ToArray();

            //convert byte[] to base64 string
            result = Convert.ToBase64String(imageBytes);
        
    

    return result;

注意:只需执行一次。不幸的是,base64 字符串太长,无法在此处发布。在下面的代码中,将 &lt;logo image as base64 string&gt; 替换为徽标图像的 base64 字符串。

如果尚未添加,请添加以下 using 语句

using System;
using System.IO;
using iText.Html2pdf;

ImageSizeType

public enum ImageSizeType

    Width,
    Height

将以下方法添加到您的代码中:

public static byte[] GetUpsLogo(int newSizeWidthOrHeight, ImageSizeType sizeType)

    byte[] imageBytes = null;

     //ToDo: add logo image as base64 string
    string upsLogoLBase64Str = <logo image as base64 string>;

    //convert base64 string to byte[]
    imageBytes = Convert.FromBase64String(upsLogoLBase64Str);

    //resize image
    imageBytes = ResizeImageMaintainingAspectRatio(imageBytes, newSizeWidthOrHeight, sizeType);

    return imageBytes;


public static string GetUpsLogoAsBase64String(int newSizeWidthOrHeight, ImageSizeType sizeType)

    string upsLogoBase64Str = string.Empty;

    //get UPS logo
    byte[] imageBytes = GetUpsLogo(newSizeWidthOrHeight, sizeType);

    //convert to base64 string
    upsLogoBase64Str = Convert.ToBase64String(imageBytes);

    return upsLogoBase64Str;


public static byte[] ResizeImageMaintainingAspectRatio(byte[] imageBytes, int newSizeWidthOrHeight, ImageSizeType sizeType)

    byte[] result = null;

    //resize image
    using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
    
        using (System.Drawing.Image img = System.Drawing.Image.FromStream(ms))
        
            int sourceWidth = img.Width;
            int sourceHeight = img.Height;
            int newWidth = 0;
            int newHeight = 0;

            if (sizeType == ImageSizeType.Width)
            
                //set value
                newWidth = newSizeWidthOrHeight;

                //calculate new height
                newHeight = newSizeWidthOrHeight * sourceHeight / sourceWidth;

            
            else
            
                //set value
                newHeight = newSizeWidthOrHeight;

                //calculate new width
                newWidth = newSizeWidthOrHeight * sourceWidth / sourceHeight;
            

            using (System.Drawing.Bitmap b = new System.Drawing.Bitmap(img, new System.Drawing.Size(newWidth, newHeight)))
            
                using (MemoryStream ms2 = new MemoryStream())
                
                    //b.Save(ms2, System.Drawing.Imaging.ImageFormat.Jpeg);
                    b.Save(ms2, System.Drawing.Imaging.ImageFormat.Gif);
                    result = ms2.ToArray();
                
            
        
    

    return result;


public static void SaveUpsLogo(string filename, int newSizeWidthOrHeight, ImageSizeType sizeType)

    //get UPS logo
    byte[] imageBytes = GetUpsLogo(newSizeWidthOrHeight, sizeType);

    //save to file
    System.IO.File.WriteAllBytes(filename, imageBytes);

如果使用“更新 2”中发布的代码,则以下代码可用于 CreatePdfFromHtmlString,因为 HTML 将不再包含徽标图像的引用。我保留了上面的原始方法,因为它可能对遇到这篇文章的其他人有用。

CreatePdfFromHtmlString

public static void CreatePdfFromHtmlString(string htmlString, string pdfFilename)

    byte[] pdfData;

    using (var memoryStream = new MemoryStream())
    
        //when specifying HTML as a string and the HTML includes
        //a resource that uses relative paths,
        //it's necessary to specify the baseUri (path) 
        //use the overload that allows baseUri to be specified

        //convert HTML to PDF
        HtmlConverter.ConvertToPdf(htmlString, memoryStream);

        //save to byte[]
        pdfData = memoryStream.ToArray();
    

    File.WriteAllBytes(pdfFilename, pdfData);

用法

string html = "<!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.0 Transitional//EN\"><HTML><HEAD><META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\"><TITLE>UPS Package Tracking</TITLE></HEAD><BODY><TABLE width=500 border=0 cellSpacing=0 cellPadding=0><TR><TD rowspan=\"30\" Width=\"17\">&nbsp;</TD><TD><TABLE cellSpacing=0 cellPadding=0 border=0 ><TR><TD align=\"left\" width=\"30\" > <IMG src=\"./ups_logo.gif\" ALT=\"UPS Logo\"></TD><TD><IMG src=\"./ups_banner.gif\" ALT=\"UPS Banner\" ></TD></TR></TABLE></TD></TR><TR><TD><TABLE cellSpacing=0 cellPadding=0 width=500 border=0 ><TR><TD colSpan=2 align=left><B>DELIVERY NOTIFICATION</B></TD><TD></TD></TR><TR><TD>&nbsp;</TD></TR><TR><TD colSpan=2>Dear Customer,</TD></TR><TR><TD>&nbsp;</TD></TR><TR><TD colSpan=3>This is in response to your request for delivery information concerning the shipment listed below.</TD></TR><TR><TD>&nbsp;</TD></TR><TR><TD align=right>Tracking Number:&nbsp;&nbsp;</TD><TD align=left>XX XXX XXX XX XXXX XXX X</TD></TR><TR><TD valign=top align=right><nobr>&nbsp;&nbsp;&nbsp;Reference Number(s):&nbsp;&nbsp;</nobr></TD><TD align=left><Table cellSpacing=0 cellPadding=0 width = 65%><TR><TD>XXXXXXXXXXXXXXXXX, XXXX, XXXXXXXXXXXXXXXXX, XXXXX5  </TD></TR></TABLE></TD></TR><TR><TD align=right>Service Type:&nbsp;&nbsp;</TD><TD align=left>UPS GROUND</TD></TR><TR><TD align=right>Package Weight:&nbsp;&nbsp;</TD><TD align=left>7.00 LBS</TD></TR><TR><TD align=right>Shipped or Billed on:&nbsp;&nbsp;</TD><TD align=left>Sep 01, 2021</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR><TR><TD align=right valign=top>Delivered on:&nbsp;&nbsp;</TD><TD align=left>Sep 07, 2021 3:10 P.M.</TD></TR><TR><TD align=right valign=top>Delivered to:&nbsp;&nbsp;</TD><TD align=left>York, NY, US, 11111</TD></TR><TR><TD align=right>Signed By:&nbsp;&nbsp;</TD><TD align=left>AngryOtter</TD></TR><TR><TD align=right>Location:&nbsp;&nbsp;</TD><TD align=left>Receiver</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>  <TR><TD colSpan=2>Thank you for giving us this opportunity to serve you.</TD></TR><TR><TD>&nbsp;</TD></TR>  <TR><TD>Sincerely,</TD></TR>  <TR><TD>United Parcel Service</TD></TR><TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR><TR><TD colSpan=2>Tracking results provided by UPS: &nbsp;Sep 16, 2021 2:02 P.M. Eastern Time (USA)</TD></TR></TABLE></TD></TR></TABLE></BODY></HTML>";

string upsLogoBase64Str = GetUpsLogoAsBase64String(100, ImageSizeType.Height);
string base64SrcStr = "data:image/gif;base64, " + upsLogoBase64Str;
html = html.Replace("./ups_logo.gif", base64SrcStr);

SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "PDF File (*.pdf)|*.pdf";

//prompt for filename to save PDF file as
if (sfd.ShowDialog() == DialogResult.OK)

    CreatePdfFromHtmlString(html, sfd.FileName);

资源

Chapter 1: Hello HTML to PDF how to set baseuri in converterproperties in itext7 html to pdf converter How to display Base64 images in HTML c# Image resizing to different size while preserving aspect ratio

【讨论】:

非常感谢您详细的撰写。不幸的是,我尝试使用 ConverterProperty 使用绝对路径和相对路径,但它仍然无法正常工作。 gif仍然丢失。我已经上传了我使用的 html 以及文件结构。 If you use a String parameter to pass your HTML, then the default value will be the folder where the code is executed. ,不使用ConverterProperty,好像还是会在当前目录中查找资源文件,那我也不知道为什么我原来的方法也不起作用。跨度> @AngryOtter:上面的代码使用带有 .gif 文件的 HTML 文件进行了测试。尝试创建以下文件夹:C:\Temp 并将 HTML 文件和图像文件放在 C:\Temp 我从 UPS API 获得了这个 HTML 字符串作为 SOAP 响应的一部分,因此它不会创建文件。相反,它需要直接从字符串转换为 PDF。 @AngryOtter:看起来 UPS 有很多 API。你用的是哪一个?

以上是关于Itext7 HtmlConverter不显示gif的主要内容,如果未能解决你的问题,请参考以下文章

当我在属性内容中使用 CSS3 函数 target-counter 时,iText7 不起作用

itext7 List序号 有序列表 解决中文不显示

无法使用 itext7 使用 Java 语言在仅 skia 生成的 pdf 上放置印章(显示倒置印章)

使用饼图生成 PDF -iText7

新手如何使用itext7生成pdf盖章

iText 7:此 pdf 文档可能无法正确显示 Firefox