C#使用wkhtmltopdf,把HTML生成PDF(包含分页)

时间:2024-03-07 13:29:37

 

最近花了2天多的时间终于把HTML生成PDF弄好了。步骤如下:

 

1、首先是技术选型。看了好多都是收费的就不考虑了。

免费的有:

  1. jsPDF(前端生成,清晰度不高,生成比较慢)
  2. iText(严格要求html标签。这个好像也是收费的)
  3. wkhtmltopdf(简单、配置选项多、生成快、支持跨平台、也支持HTML生成图片) 

因此选择wkhtmltopdf。

 

2、前期准备,首先需要下载wkhtmltopdf.exe(下载地址:https://wkhtmltopdf.org/downloads.html)阅读配置参数(https://wkhtmltopdf.org/usage/wkhtmltopdf.txt

常用参数:

  1. -T 0 :设置上下左右margin-top=0(-B 0 -L 0 -R 0 -T 0,上下左右都设置一下)
  2. -s A4:设置A4纸大小,默认A4
  3. --disable-smart-shrinking:禁止缩放(不设置这个,生成的pdf会缩放)
  4. --zoom 1:设置缩放系数,默认为1。如果--disable-smart-shrinking设置了,--zoom就不用设置了。
  5. --cookie name value:设置cookie,如果下载的url需要登录(用cookie),那么这个参数很重要。

 

3、设置需要打印的页面(核心是分页)

A4纸大小:210mm×297mm,因此页面的每个div大小也是A4纸大小。

 

这里的页面设置很重要。另外,设置了分页的页码,示例如下:

<style>
#view {
    height: 100%;
    margin: auto;
    padding: 0;
    width: 210mm;
}

/*设置A4打印页面*/
/*备注:由于@是否特殊符号,样式放在css文件中没问题,放在cshtml文件就不行了,需要@@。*/
@preview-item {
    size: A4;
    margin: 0;
}
 
@media print {
    .preview-item {
        margin: 0;
        border: initial;
        border-radius: initial;
        width: initial;
        min-height: initial;
        box-shadow: initial;
        background: initial;
        page-break-after: always;
    }
}
.preview-item {
    width: 100%;
    height: 297mm;
    position: relative;
}

.page-view {
    position: absolute;
    width: 100%;
    text-align: center;
    height: 60px;
    line-height: 60px;
    bottom: 0;
}
</style>

<div id="view">
    <div class="preview-item">
        <div class="preview-item-body">这是第一页</div>
        <div class="page-view">1/3</div>
    </div>
    <div class="preview-item">
        <div class="preview-item-body">这是第二页</div>
        <div class="page-view">2/3</div>
    </div>
    <div class="preview-item">
        <div class="preview-item-body">这是第三页</div>
        <div class="page-view">3/3</div>
    </div>
</div>

 

  

4、C#代码实现(核心是Arguments的设置)

        /// <summary>
        /// HTML生成PDF
        /// </summary>
        /// <param name="url">url地址(需要包含HTTP://)</param>
        /// <param name="path">PDF存放路径(可以是aaa.pdf,也可以用路径,只能是绝对地址,如:D://aaa.pdf)</param>
        public static bool HtmlToPdf(string url, string path)
        {
            path = HttpContext.Current.Server.MapPath(path);string cookie = "cookieKey cookieValue";//改为为你自己的
            string Arguments = "-q  -B 0 -L 0 -R 0 -T 0 -s A4 --no-background --disable-smart-shrinking --cookie " + cookie + " " + url + " " + path; //参数可以根据自己的需要进行修改

            try
            {
                if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(path))
                    return false;
                var p = new Process();
                string str = HttpContext.Current.Server.MapPath("/htmlToPDF/wkhtmltopdf.exe");
                if (!File.Exists(str))
                    return false;
                p.StartInfo.FileName = str;
                p.StartInfo.Arguments = Arguments;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardInput = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.CreateNoWindow = false;
                p.Start();
                p.WaitForExit();
                System.Threading.Thread.Sleep(1000);

                return true;
            }
            catch (Exception ex)
            {
                LogHelper.WriteError(ex);
            }
            return false;
        }

 

 

方法的调用:

            string url = Request.Url.AbsoluteUri.Replace("DownloadPDF", "Detail");//DownloadPDF是下载页面,Detail是上面的HTML页面
            string pdfDirectory = "/Data/PDF/";
            if (!System.IO.Directory.Exists(HttpContext.Current.Server.MapPath(pdfDirectory)))
            {
                System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(pdfDirectory));
            }
            string path = pdfDirectory + Guid.NewGuid() + ".pdf";
            HtmlToPdf(url, path);

            if (!System.IO.File.Exists(Utils.GetMapPath(path)))//如果生成失败,重试一次
            {
                HtmlToPdfHelper.HtmlToPdf(url, path);
            }

            if (!System.IO.File.Exists(Utils.GetMapPath(path)))//如果生成失败,重试一次
            {
                HtmlToPdfHelper.HtmlToPdf(url, path);
            }    

  

5、ok,采坑结束~