使用iTextSharp在C#中将图像转换为PDF

4

我想使用iTextSharp将包含图片和GridView的页面转换为PDF格式。以下是我的代码

  string attachment = "attachment; filename=Report.pdf";
        Response.ClearContent();
        Response.AddHeader("content-disposition", attachment);
        Response.ContentType = "application/pdf";
        StringWriter stw = new StringWriter();
        HtmlTextWriter htextw = new HtmlTextWriter(stw);
        divText.RenderControl(htextw);   //image is place inside 
        GridView1.RenderControl(htextw);           
        Document document = new Document();
        PdfWriter.GetInstance(document, Response.OutputStream);
        document.Open();
        StringReader str = new StringReader(stw.ToString());
        HTMLWorker htmlworker = new HTMLWorker(document);
        htmlworker.Parse(str);
        document.Close();
        Response.Write(document);
        Response.End();

我成功地将GridView转换为PDF,但无法转换图像。该图像位于名为divText的div内。有人能帮助我吗?


1
图片是如何引用的?Base64-URL?相对URL?绝对URL? - mkl
1
无关紧要,但请删除Response.Write(document);这一行代码,该代码会在Document对象上调用ToString()方法,而该方法并未重写默认值,因此您实际上是将文本iTextSharp.text.Document写入每个文件的末尾,最终可能导致PDF文件损坏。 - Chris Haas
回到问题本身,我们需要看到 stw.ToString() 的缩写版本,因为 HTMLWorker 只能处理 HTML,而不是 GridView,这才是最重要的。 - Chris Haas
4个回答

3
我建议尝试以下代码,并根据您的需要进行修改。
public static void ConvertImageToPdf(string srcFilename, string dstFilename)
    {
        iTextSharp.text.Rectangle pageSize = null;

        using (var srcImage = new Bitmap(srcFilename))
        {
            pageSize = new iTextSharp.text.Rectangle(0, 0, srcImage.Width, srcImage.Height);
        }
        using (var ms = new MemoryStream())
        {
            var document = new iTextSharp.text.Document(pageSize, 0, 0, 0, 0);
            iTextSharp.text.pdf.PdfWriter.GetInstance(document, ms).SetFullCompression();
            document.Open();
            var image = iTextSharp.text.Image.GetInstance(srcFilename);
            document.Add(image);
            document.Close();

            File.WriteAllBytes(dstFilename, ms.ToArray());
        }
    }

此外,还可以参考这个问题

上述代码的解释,请点击此处

iTextSharp中处理图像


在调用getinstance时,我遇到了"对象引用未设置为对象的实例"错误。 - MindRoasterMir
请注意,在非Windows环境下无法使用位图(Bitmap)。 https://learn.microsoft.com/fr-fr/dotnet/core/compatibility/core-libraries/6.0/system-drawing-common-windows-only - undefined

0

你的代码样例看起来不错,但是缺少对IImageProvider的实现。默认情况下,HTMLWorker只能处理绝对URL的图像。因此,这里提供了一个简单的实现供您参考:

// handle <img> tags in any System.Web.UI.Control (GridView) with:
// 1. base64 Data URI scheme - https://en.wikipedia.org/wiki/Data_URI_scheme
// 2. relative URLs on local server
// 3. absolute URLs on a remote/local server (DEFAULT)
public class ImageHander : IImageProvider
{
    public string BaseUri { get; set; }
    public static Regex Base64 = new Regex(
        @"^data:image/(?<mediaType>[^;]+);base64,(?<data>.*)",
        RegexOptions.Compiled
    );

    // alias: using iTextImage = iTextSharp.text.Image;
    public iTextImage GetImage(string src,
        IDictionary<string, string> attrs,
        ChainedProperties chain,
        IDocListener doc)
    {
        Match match;
        // [1]
        if ((match = Base64.Match(src)).Length > 0)
        {
            return iTextImage.GetInstance(
                Convert.FromBase64String(match.Groups["data"].Value)
            );
        }

        // [2]
        if (!src.StartsWith("http", StringComparison.OrdinalIgnoreCase))
        {
            src = HttpContext.Current.Server.MapPath(
                new Uri(new Uri(BaseUri), src).AbsolutePath
            ); 
        }
        return iTextImage.GetInstance(src);
    }
}

然后您可以在代码后台中像这样使用实现(按钮事件处理程序):

protected void ProcessHtml(object sender, CommandEventArgs e)
{
    Response.ContentType = "application/pdf";
    Response.AppendHeader("Content-Disposition", "attachment; filename=table.pdf");
    using (Document document = new Document())
    {
        PdfWriter.GetInstance(document, Response.OutputStream);
        document.Open();

        var html = new StringBuilder();
        using (var stringWriter = new StringWriter(html))
        {
            using (var htmlWriter = new HtmlTextWriter(stringWriter))
            {
                // replace 'ConvertControlToPdf' with **YOUR** GridView control Id!
                ConvertControlToPdf.RenderControl(htmlWriter);
            }
        }

        var providers = new Dictionary<string, Object>();
        // HTMLWorker does **NOT** understand relative URLs, so
        // make existing ones in HTML source absolute, and handle 
        // base64 Data URI schemes
        var ih = new ImageHander() { BaseUri = Request.Url.ToString() };

        // dictionary key 'img_provider' is **HARD-CODED**, in 
        // iTextSharp 5.0.0 - 5.0.5, so you may need to use next line
        // providers.Add("img_provider", ih);
        providers.Add(HTMLWorker.IMG_PROVIDER, ih);
        //            ^^^^^^^^^^^^^^^^^^^^^^^ - constant added in 5.0.6
        using (var sr = new StringReader(html.ToString()))
        {
            foreach (IElement element in HTMLWorker.ParseToList(
                sr, null, providers))
            {
                PdfPTable table = element as PdfPTable;
                document.Add(element);
            }
        }
    }
    Response.End();
}

不确定您正在运行哪个版本的iTextSharp,请注意上面的HTMLWorker.IMG_PROVIDERconst的内联注释。


0

将图像的URL路径更改为"C:\images\Filename.jpg"


0
关于Pushkar Phule的回答,我在这里给出了使用另一个在非Windows环境下工作的库(SkiaSharp)的解决方案。
    using itextSharp.text;
    using itextSharp.text.pdf;
    using SkiaSharp;

    ...

    private byte[] ConvertImageToPdf(byte[] file)
    {
        var bitmap = SKBitmap.Decode(file);

        Rectangle pageSize = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

        using var ms = new MemoryStream();
        var document = new Document(pageSize, 0, 0, 0, 0);
        PdfWriter.GetInstance(document, ms).SetFullCompression();
        document.Open();
        var image = Image.GetInstance(new MemoryStream(file));
        document.Add(image);
        document.Close();

        return ms.ToArray();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接