首页 > 代码库 > 怎么将网页Html转化为PDF

怎么将网页Html转化为PDF

前言
     之前做了有个项目要求将Html转成PDF,网上搜索答案大部分都是使用itextsharp组件进行转换,在实际使用过程中发现不是很好使用。现在本人推荐使用wkhtmltox.exe这个应用进行PDF转换。
         
  
wkhtmltox.exe开发步骤
       1、安装wkhtmltox.exe,安装完后在安装路径会有:\wkhtmltopdf\bin\wkhtmltopdf.exe,这个事我们用来转化PDF的工具。下载地址为:https://sourceforge.net/projects/wkhtmltopdf/
        2、编写代码调用需要转换为PDF
              2.1  主要生产PDF的PDFConverter类,里面主要的方法为:ConvertHtmlToPDF
                     其中有两重载的方法:void ConvertHtmlToPdf(PdfDocument document, PdfOutput output) 和 void ConvertHtmlToPdf(PdfDocument document, PdfConvertEnvironment environment, PdfOutput woutput)
PDFConverter的代码为:
  using System;using System.Collections.Generic;using System.Diagnostics;using System.IO;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace PDFApplication{    public class PdfConvertException : Exception    {        public PdfConvertException(String msg)            : base(msg)        {        }    }    public class PdfConvertTimeoutException : PdfConvertException    {        public PdfConvertTimeoutException()            : base("HTML to PDF conversion process has not finished in the given period.")        {        }    }    public class PdfOutput    {        public String OutputFilePath { get; set; }        public Stream OutputStream { get; set; }        public Action<PdfDocument, byte[]> OutputCallback { get; set; }    }    public class PdfDocument    {        public String Url { get; set; }        public String Html { get; set; }        public String HeaderUrl { get; set; }        public String FooterUrl { get; set; }        public String HeaderLeft { get; set; }        public String HeaderCenter { get; set; }        public String HeaderRight { get; set; }        public String FooterLeft { get; set; }        public String FooterCenter { get; set; }        public String FooterRight { get; set; }        public object State { get; set; }        public Dictionary<String, String> Cookies { get; set; }        public Dictionary<String, String> ExtraParams { get; set; }    }    public class PdfConvertEnvironment    {        public String TempFolderPath { get; set; }        public String WkHtmlToPdfPath { get; set; }        public int Timeout { get; set; }        public bool Debug { get; set; }    }    public class PDFConverter    {        private static PdfConvertEnvironment _e;        public static PdfConvertEnvironment Environment        {            get            {                if (_e == null)                    _e = new PdfConvertEnvironment                    {                        TempFolderPath = Path.GetTempPath() + @"\pdf\",                        WkHtmlToPdfPath = GetWkhtmlToPdfExeLocation(),                        Timeout = 60000                    };                return _e;            }        }        private static string GetWkhtmlToPdfExeLocation()        {            string programFilesPath = @"C:\Program Files";            string filePath = Path.Combine(programFilesPath, @"wkhtmltopdf\wkhtmltopdf.exe");            if (File.Exists(filePath))                return filePath;            string programFilesx86Path = System.Environment.GetEnvironmentVariable("ProgramFiles");            filePath = Path.Combine(programFilesx86Path, @"wkhtmltopdf\wkhtmltopdf.exe");            if (File.Exists(filePath))                return filePath;            filePath = Path.Combine(programFilesPath, @"wkhtmltopdf\bin\wkhtmltopdf.exe");            if (File.Exists(filePath))                return filePath;            return Path.Combine(programFilesx86Path, @"wkhtmltopdf\bin\wkhtmltopdf.exe");        }        public static void ConvertHtmlToPdf(PdfDocument document, PdfOutput output)        {            ConvertHtmlToPdf(document, null, output);        }        public static void ConvertHtmlToPdf(PdfDocument document, PdfConvertEnvironment environment, PdfOutput woutput)        {            if (document.Url == "-" && document.Html == null)                throw new PdfConvertException(                    String.Format("You must supply a HTML string, if you have enterd the url: {0}", document.Url)                );            if (environment == null)                environment = Environment;            String outputPdfFilePath;            bool delete;            if (woutput.OutputFilePath != null)            {                outputPdfFilePath = woutput.OutputFilePath;                delete = false;            }            else            {                outputPdfFilePath = Path.Combine(environment.TempFolderPath, String.Format("{0}.pdf", Guid.NewGuid()));                delete = true;            }            if (!File.Exists(environment.WkHtmlToPdfPath))                throw new PdfConvertException(String.Format("File ‘{0}‘ not found. Check if wkhtmltopdf application is installed.", environment.WkHtmlToPdfPath));            StringBuilder paramsBuilder = new StringBuilder();            paramsBuilder.Append("--page-size A4 ");            if (!string.IsNullOrEmpty(document.HeaderUrl))            {                paramsBuilder.AppendFormat("--header-html {0} ", document.HeaderUrl);                paramsBuilder.Append("--margin-top 25 ");                paramsBuilder.Append("--header-spacing 5 ");            }            if (!string.IsNullOrEmpty(document.FooterUrl))            {                paramsBuilder.AppendFormat("--footer-html {0} ", document.FooterUrl);                paramsBuilder.Append("--margin-bottom 25 ");                paramsBuilder.Append("--footer-spacing 5 ");            }            if (!string.IsNullOrEmpty(document.HeaderLeft))                paramsBuilder.AppendFormat("--header-left \"{0}\" ", document.HeaderLeft);            if (!string.IsNullOrEmpty(document.FooterCenter))                paramsBuilder.AppendFormat("--header-center \"{0}\" ", document.HeaderCenter);            if (!string.IsNullOrEmpty(document.FooterCenter))                paramsBuilder.AppendFormat("--header-right \"{0}\" ", document.HeaderRight);            if (!string.IsNullOrEmpty(document.FooterLeft))                paramsBuilder.AppendFormat("--footer-left \"{0}\" ", document.FooterLeft);            if (!string.IsNullOrEmpty(document.FooterCenter))                paramsBuilder.AppendFormat("--footer-center \"{0}\" ", document.FooterCenter);            if (!string.IsNullOrEmpty(document.FooterCenter))                paramsBuilder.AppendFormat("--footer-right \"{0}\" ", document.FooterRight);            if (document.ExtraParams != null)                foreach (var extraParam in document.ExtraParams)                    paramsBuilder.AppendFormat("--{0} {1} ", extraParam.Key, extraParam.Value);            if (document.Cookies != null)                foreach (var cookie in document.Cookies)                    paramsBuilder.AppendFormat("--cookie {0} {1} ", cookie.Key, cookie.Value);            paramsBuilder.AppendFormat("\"{0}\" \"{1}\"", document.Url, outputPdfFilePath);            try            {                StringBuilder output = new StringBuilder();                StringBuilder error = new StringBuilder();                using (Process process = new Process())                {                    process.StartInfo.FileName = environment.WkHtmlToPdfPath;                    process.StartInfo.Arguments = paramsBuilder.ToString();                    process.StartInfo.UseShellExecute = false;                    process.StartInfo.RedirectStandardOutput = true;                    process.StartInfo.RedirectStandardError = true;                    process.StartInfo.RedirectStandardInput = true;                    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))                    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))                    {                        DataReceivedEventHandler outputHandler = (sender, e) =>                        {                            if (e.Data =http://www.mamicode.com/= null)                            {                                outputWaitHandle.Set();                            }                            else                            {                                output.AppendLine(e.Data);                            }                        };                        DataReceivedEventHandler errorHandler = (sender, e) =>                        {                            if (e.Data =http://www.mamicode.com/= null)                            {                                errorWaitHandle.Set();                            }                            else                            {                                error.AppendLine(e.Data);                            }                        };                        process.OutputDataReceived += outputHandler;                        process.ErrorDataReceived += errorHandler;                        try                        {                            process.Start();                            process.BeginOutputReadLine();                            process.BeginErrorReadLine();                            if (document.Html != null)                            {                                using (var stream = process.StandardInput)                                {                                    byte[] buffer = Encoding.UTF8.GetBytes(document.Html);                                    stream.BaseStream.Write(buffer, 0, buffer.Length);                                    stream.WriteLine();                                }                            }                            if (process.WaitForExit(environment.Timeout) && outputWaitHandle.WaitOne(environment.Timeout) && errorWaitHandle.WaitOne(environment.Timeout))                            {                                if (process.ExitCode != 0 && !File.Exists(outputPdfFilePath))                                {                                    throw new PdfConvertException(String.Format("Html to PDF conversion of ‘{0}‘ failed. Wkhtmltopdf output: \r\n{1}", document.Url, error));                                }                            }                            else                            {                                if (!process.HasExited)                                    process.Kill();                                throw new PdfConvertTimeoutException();                            }                        }                        finally                        {                            process.OutputDataReceived -= outputHandler;                            process.ErrorDataReceived -= errorHandler;                        }                    }                }                if (woutput.OutputStream != null)                {                    using (Stream fs = new FileStream(outputPdfFilePath, FileMode.Open))                    {                        byte[] buffer = new byte[32 * 1024];                        int read;                        while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)                            woutput.OutputStream.Write(buffer, 0, read);                    }                }                if (woutput.OutputCallback != null)                {                    byte[] pdfFileBytes = File.ReadAllBytes(outputPdfFilePath);                    woutput.OutputCallback(document, pdfFileBytes);                }            }            finally            {                if (delete && File.Exists(outputPdfFilePath))                    File.Delete(outputPdfFilePath);            }        }    }}  2、在程序集中调用该方法      using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;namespace PDFApplication{    class Program    {        static void Main(string[] args)        {            PDFConverter.ConvertHtmlToPdf(new PdfDocument            {                Url = "http://www.cnblogs.com/",                HeaderLeft = "[title]",                //HeaderRight = "[date] [time]",                // FooterCenter = "Page [page] of [topage]"            }, new PdfOutput            {                OutputFilePath = "博客园.pdf",                OutputCallback = (p,q) =>                {                    FileStream fileStream = null;                    try                    {                        string fileName = AppDomain.CurrentDomain.BaseDirectory + "/PDF/" + Guid.NewGuid() + ".pdf";                        if(Directory.Exists(fileName) )                        {                            Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "/PDF/");                        }                        fileStream = new FileStream(fileName, FileMode.OpenOrCreate);                        fileStream.Write(q, 0, q.Length);                    }                    catch(Exception ex)                    {                    }                    finally                    {                        if (fileStream != null)                        {                            fileStream.Close();                        }                    }                }            });        }    }}

 

3、本人试验转化的PDF为
技术分享
 技术分享
4、结论
    生产PDF的步骤为:
   1、安装wkhtmltox.exe;
   2、根据自己的情况调整PDFConverter的参数
   3、调用PDFConverter生成PDF

怎么将网页Html转化为PDF