Itext7 HtmlConverter 不显示gif

Itext7 HtmlConverter does not display gif

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

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

这是动态 HTML 我从 API.

当我像这样使用 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

编辑:我的 request/response 代码:

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

感谢任何帮助

根据pdfHTML: configuration options

ConverterProperties: Through the various method overloads, you can specify certain input parameter types in the first two arguments, but there is always the optional third parameter ConverterProperties. This parameter contains the basic configuration options that allow users to customize handling of the input data in various ways. We will now elaborate on these options so that you can configure your pdfHTML code for optimal results.

baseUri: If the HTML file requires any external resources, such as a standalone CSS file or image files, then pdfHTML file needs to know where these are located. That location may either be a URI on the local file system or online.

pdfHTML will try to use a reasonable default value in case you don't specify a baseUri. If you use a String parameter to pass your HTML, then the default value will be the folder where the code is executed. If you use the overload of convertToPdf with a File parameter, it will use the same location as the input file.

If neither of these defaults is right for you, then you will need to define the default resource location root. Then, any references in the HTML file will start from that path to find the resource. It is possible to use the ../ syntax to go up in the directory tree of your file system, but for other purposes, the specified URI acts as the root folder for determining paths.

先决条件:

  • Download/install NuGet 包 itext7
  • Download/install 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 字符串 - 您会找到徽标.zip 文件中“Common and 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 字符串太长,无法在此处 post。在下面的代码中,将 <logo image as base64 string> 替换为徽标图像的 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”中的代码 post,以下代码可用于 CreatePdfFromHtmlString,因为 HTML 将不再包含徽标的引用图片。我保留了上面的原始方法,因为它可能对遇到此问题的其他人有用 post.

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

资源: