Unable to Export HTML Markup to PDF using iTextSharp API in asp.net using C#?

强颜欢笑 提交于 2019-12-02 08:29:51
Björn

Take a look at: creating pdf with itextsharp with images from database

You need to either provide the full physical path in the src-attribute of every img-elements (e.g. <img src="c:\myproject\images\image.jpg"/>) or there is a possibility to tell iTextSharp the physical base folder for all your images.

I was able to render my html correctly by useiung special providers

var baseUrl = string.Format("{0}://{1}", Request.Url.Scheme, Request.Url.Authority);

var html = ...;

Response.Clear();
Response.ClearContent();
Response.ClearHeaders();

Response.ContentEncoding = Encoding.UTF8;
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.pdf", fileName));
Response.ContentType = "application/pdf";

using (var ms = new MemoryStream())
{

    using (var doc = new Document())
    {                       
        using (var writer = PdfWriter.GetInstance(doc, ms))
        {
            doc.Open();

            var rootProvider = new CustomRootProvider(baseUrl, Request.PhysicalApplicationPath); //Server.MapPath(Request.ApplicationPath)

            FontFactory.RegisterDirectories();

            var htmlContext = new HtmlPipelineContext(null);

            htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());                           

            htmlContext.SetImageProvider(rootProvider);

            htmlContext.SetLinkProvider(rootProvider);

            htmlContext.CharSet(Encoding.UTF8);

            var cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true);

            var pipeline = new CssResolverPipeline(cssResolver,

            new HtmlPipeline(htmlContext, new PdfWriterPipeline(doc, writer)));

            var worker = new XMLWorker(pipeline, true);

            var p = new XMLParser(worker);

            using(var htmlStream = new MemoryStream(Encoding.UTF8.GetBytes(html)))
            {
                p.Parse(htmlStream, Encoding.UTF8);                         
            }       

            writer.CloseStream = false;
        }
        doc.Close();
    }
    ms.Position = 0;                    
    Response.BinaryWrite(ms.ToArray());
}

Response.Flush();
Response.End();

...

public class CustomRootProvider : AbstractImageProvider, ILinkProvider
{
    private string _baseUrl;
    private string _basePath;
    public CustomRootProvider(string baseUrl, string basePath)
    {
        _baseUrl = baseUrl;     
    }

    public override Image Retrieve(string src)
    {       
        var siteUrl = string.IsNullOrEmpty(_baseUrl) ? HttpContext.Current.Request.Url.AbsoluteUri.Replace(HttpContext.Current.Request.Url.PathAndQuery, string.Empty) : _baseUrl;

        siteUrl = VirtualPathUtility.RemoveTrailingSlash(siteUrl);      

        if (Uri.IsWellFormedUriString(src, UriKind.Relative))
        {
            src = new Uri(new Uri(siteUrl), src).ToString();            
        }

        try
        {
            return Image.GetInstance(src);
        }
        catch (Exception)
        {                       
            return Image.GetInstance(new Uri(new Uri(siteUrl), "/Content/Images/noimage.png").ToString());
        }

    }

    public override string GetImageRootPath()
    {
        return string.IsNullOrEmpty(_basePath) ? HttpContext.Current.Request.PhysicalApplicationPath : _basePath;
        //HttpContext.Current.Server.MapPath(HttpContext.Current.Request.ApplicationPath);
    }

    public string GetLinkRoot()
    {
        return string.IsNullOrEmpty(_baseUrl)
            ? HttpContext.Current.Request.Url.AbsoluteUri.Replace(HttpContext.Current.Request.Url.PathAndQuery, string.Empty)
            : _baseUrl;
    }
}

But was having strange problems with html unicode symbols on some hosting machines (ok in german machine but incorrect rendering on russian). I was trying to register differern fonts with iTextSharp fontfactory, to play with different markup (css rules, font-faces etc). Nothing helped me. This was ended with using wkhtmltopdf with wrapper Pechkin (different wrappers available on the internet). wkhtmltopdf works just great out of the box!:

var config = new GlobalConfig().SetMargins(0, 0, 0, 0).SetPaperSize(PaperKind.A4);

var pdfWriter = new SynchronizedPechkin(config);

var bytes = pdfWriter.Convert(new Uri(dataUrl));

Response.BinaryWrite(bytes);

Highly recommend!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!