日有网友希望有一篇用PHP生成PDF的文章教程,好的今天我们就讲一讲怎么样用PHP将HTML生成PDF
我们使用的开源类库就是TCPDF
GITHUB地址:
https://github.com/tecnickcom/TCPDF
composer安装:
composer require tecnickcom/tcpdf
demo示例:
https://tcpdf.org/examples/
这里主要讲的是讲HTML生成PDF因为HTML格式绝大部分够用了,其它个性化的功能大家看下官方的DEMO就行了比如生成图表等
下面说下具体使用方式:
1.实例化TCPDF对象
$pdf = new TCPDF(PDF_PAGE_ORIENTATIN, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
2.设置标题关键字等(步骤可以省略)
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Nicola Asuni');
$pdf->SetTitle('TCPDF演示');
$pdf->SetSubject('TCPDF Tutorial');
$pdf->SetKeywords('TCPDF, PDF, example, test, guide');
3.设置字体(这步很重要不然中文乱码)
$fontname = TCPDF_FONTS::addTTFfont('Droid Sans Fallback.ttf', 'TrueTypeUnicode', '', 32);
$pdf->SetFont($fontname, '', 20);
4.添加个页面
$pdf->AddPage();
5.将HTML生成PDF
$pdf->writeHTML($html);
6.输出(默认直接在浏览器显示)
$pdf->Output();
$pdf->Output('123.pdf','D');//这个是下载,其他方式请替换参数
7.生成后的效果
链接列表等演示
生成图片演示
表格演示
最后总结:
1.一定要设置字体,否则中文乱码。最好使用文本的设置方法和字体。网上的设置字体的方法虽然能解决但是用pdfparser这个类读取生成后的PDF内容还是乱码(读取PDF内容的方法在我另一篇文章中有说到)
2.如果你设置了PDF的头和脚 还需在设置一遍字体
$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, 'PDF头部标题', '代码庸医');
$pdf->setHeaderFont(Array($fontname, '', PDF_FONT_SIZE_MAIN));
好东西要分享,之前一直在使用wkhtmltopdf进行pdf文件的生成,常用的方式就是先安装wkhtmltopdf,然后在程序中用命令的方式将对应的html生成pdf文件,简单而且方便;但重复的编码使得想在wkhtmltopdf基础上进行封装,偶然间发现有小伙伴已经封装的还不错啦,常用的功能都已经实现,源码地址:https://github.com/fpanaccia/Wkhtmltopdf.NetCore。
作者将其打包成Nuget包(Wkhtmltopdf.NetCore),直接引入使用即可;
既然用到了.NetCore,肯定就要考虑到跨平台兼容性,对于wkhtmltopdf之前一直是在Windows上使用,还没有在其他平台尝试;这个包封装的行不行,拉出来遛遛就知道啦,接下来就试试:
1. 建个API项目,引入包和兼容对应平台的wkhtmltopdf执行文件;
注: 默认依赖的wkhtmltopdf执行文件需要存放在Rotativa目录下,可以自定义名称,如果自定义,需要再注册服务时指定对应的文件名;这里的wkhtmltopdf已经根据不同平台进行编译打包了,无需安装,这些文件在源码那就有;
2.创建PDFTestController控制器,添加如下接口进行测试;
首先把生成pdf的服务注入进来,后续直接使用就可以啦:
接下来就开始写接口啦,这里只是测试,代码冗余没有考虑,在实际项目中小伙伴可以根据自己需求进行封装;
ConvertOptions默认封装了以下属性,小伙伴也可以自定义扩展,只要继承IConvertOptions即可,这里就不演示的,因为官方有对应的案例,下伙伴下去搞搞,wkhtmltopdf的参数挺多的,都可以进行封装使用。
根据指定视图生成对应的pdf效果,如下:
根据指定视图生成对应的pdf效果,如下:
如上基本的使用演示就说那么多,使用还是很简单,小伙伴后续可以根据自己的需要进行相关扩展;当然还有其他功能,比如设置页眉/页脚等,作者提供有对应的案例;这里不说那么多,不然又是长文。
3. 小伙伴用的时候可能会遇到的问题
看见这个错我懵的,一顿搜索猛如虎,还是没找到答案;冷静下来,重新捋捋,原来是自己在犯傻;
两个问题需要解决,1.上传到Linux下的wkhtmltopdf没有给执行权限;2.可能环境缺少对应的依赖库;
设置可执行权限
在Linux环境下,可以通过ll命令查看权限,刚开始是没有权限的,只需要执行chmod 777 wkhtmltopdf命令,执行权限就有了,如下图中红框中的x就是可执行权限;关于Linux常用命令后续单独整理一篇分享吧,这里先不延伸。
安装缺少的依赖库
可执行权限开启之后,别急着去访问页面,这样可能还是错误。因为可能缺少依赖库,那咋知道缺少呢,我是直接执行wkhtmltopdf,执行成功就没啥,不成功就会报缺少相关依赖,然后直接安装就行啦;执行./wkhtmltopdf https://www.baidu.com ./test.pdf试试就知道啦,因为wkhtmltopdf本身是可以单独运行的,并不依赖我们写的程序。
链接: https://pan.baidu.com/s/1jikC0DUkpEzpXL5ysjEQPA 提取码: tn4j ;
将下载下来的字体解压,然后拷贝到Linux下的 /usr/share/fonts目录下即可
最后这样应该就没啥问题啦,剩下的就交给小伙伴自己摸索搞实践吧;
此文源码地址:https://github.com/zyq025/DotNetCoreStudyDemo
wkhtmltopdf官网地址:https://wkhtmltopdf.org/
使用还是很简单的,常规的需求没啥问题,如果需要功能定制化,小伙伴可以参考源码,自己封装一个(封装思路不难的); 如果小伙伴有比较好的导出库,免费开源的那种,一起分享出来玩玩。
感谢小伙伴的:点赞、收藏和评论,下期继续~~~
一个被程序搞丑的帅小伙,关注"Code综艺圈",跟我一起学~~~
.NET的SelectPdf Html到Pdf转换器-社区版是.NET的SelectPdf库中提供的功能强大的html到pdf转换器的免费版本。
转换器提供了许多强大的选项(将任何网页转换为pdf,将任何html字符串转换为pdf,html5 / css3 / javascript支持,页眉和页脚支持等),唯一的限制是它最多可以生成pdf文档。5页长。
.NET的免费HTML至Pdf转换器–社区版功能:最多生成5页pdf文档,将任何网页转换为pdf,将任何原始html字符串转换为pdf,设置pdf页面设置(页面大小,页面方向,页面边距) ,在转换过程中调整内容大小以适合pdf页面,设置pdf文档属性,设置pdf查看器首选项,设置pdf安全性(密码,权限),设置转换延迟和网页导航超时,自定义页眉和页脚,在页眉中支持html和页脚,自动和手动分页符,在每个页面上重复html表头,支持@media类型屏幕和打印,支持内部和外部链接,基于html元素自动生成书签,支持HTTP标头,支持HTTP cookie,支持需要身份验证的网页,支持代理服务器,启用/禁用javascript,修改颜色空间,多线程支持,HTML5 / CSS3支持,Web字体支持等等。
1、nuget 引用
Install-Package Select.HtmlToPdf
2、方法
using SelectPdf;
using System.Collections.Specialized;
using System.IO;
using System.Web;
namespace BQoolCommon.Helpers.File
{
public class WebToPdf
{
public WebToPdf()
{
//SelectPdf.GlobalProperties.LicenseKey = "your-license-key";
}
/// <summary>
/// 將 Html 轉成 PDF,並儲存成檔案
/// </summary>
/// <param name="html">html</param>
/// <param name="fileName">絕對路徑</param>
public void SaveToFileByHtml(string html, string fileName)
{
var doc = SetPdfDocument(html);
doc.Save(fileName);
}
/// <summary>
/// 傳入 Url 轉成 PDF,並儲存成檔案
/// </summary>
/// <param name="url">url</param>
/// <param name="fileName">絕對路徑</param>
/// <param name="httpCookies">Cookies</param>
public void SaveToFileByUrl(string url, string fileName, NameValueCollection httpCookies)
{
var doc = SetPdfDocument(url, httpCookies);
doc.Save(fileName);
}
/// <summary>
/// 將 Html 轉成 PDF,並輸出成 byte[] 格式
/// </summary>
/// <param name="html">html</param>
/// <returns></returns>
public byte[] GetFileByteByHtml(string html)
{
var doc = SetPdfDocument(html);
return doc.Save();
}
/// <summary>
/// 傳入 Url 轉成 PDF,並輸出成 byte[] 格式
/// </summary>
/// <param name="url">url</param>
/// <param name="httpCookies">Cookies</param>
/// <returns></returns>
public byte[] GetFileByteByUrl(string url, NameValueCollection httpCookies)
{
var doc = SetPdfDocument(url, httpCookies);
return doc.Save();
}
/// <summary>
/// 將 Html 轉成 PDF,並輸出成 Stream 格式
/// </summary>
/// <param name="html">html</param>
/// <returns></returns>
public Stream GetFileStreamByHtml(string html)
{
var doc = SetPdfDocument(html);
var pdfStream = new MemoryStream();
doc.Save(pdfStream);
pdfStream.Position = 0;
return pdfStream;
}
/// <summary>
/// 傳入 Url 轉成 PDF,並輸出成 Stream 格式
/// </summary>
/// <param name="html">html</param>
/// <returns></returns>
public Stream GetFileStreamByUrl(string url, NameValueCollection httpCookies)
{
var doc = SetPdfDocument(url, httpCookies);
var pdfStream = new MemoryStream();
doc.Save(pdfStream);
pdfStream.Position = 0;
return pdfStream;
}
private PdfDocument SetPdfDocument(string html)
{
var converter = new HtmlToPdf();
converter.Options.WebPageWidth = 1200;
html = HttpUtility.HtmlDecode(html);
return converter.ConvertHtmlString(html);
}
private PdfDocument SetPdfDocument(string url, NameValueCollection httpCookies)
{
var converter = new HtmlToPdf();
converter.Options.WebPageWidth = 1200;
if (httpCookies != && httpCookies.Count != 0)
{
converter.Options.HttpCookies.Add(httpCookies);
}
return converter.ConvertUrl(url);
}
}
}
3、调用
/// <summary>
/// 下载pdf
/// </summary>
public void Downpdf(string data)
{
var stream = new BQoolCommon.Helpers.File.WebToPdf().GetFileStreamByHtml(Gethtml(data));
Response.Clear();
//二进制流数据(如常见的文件下载)
Response.ContentType = "application/octet-stream";
//通知浏览器下载文件而不是打开
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode("Profit and Loss Statement.pdf", System.Text.Encoding.UTF8));
var bytes = StreamToBytes(stream);
Response.BinaryWrite(bytes);
Response.Flush();
stream.Close();
stream.Dispose();
Response.End();
}
那么如何获取指定页面的html 呢 传入对应的model 获得指定动态的html
private string Gethtml(string data)
{
string str = "";
str = this.ControllerContext.RenderViewToString("ProfitDetails", data);
return str;
}
using BQoolCommon.Helpers.Format;
using Newtonsoft.Json;
using OrdersManager.Models.ViewModel.Report;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace OrdersManager.Web.Infrastructure
{
public static class HelperExtensions
{
public static string RenderViewToString(this ControllerContext context, string viewName, string data)
{
if (string.IsOrEmpty(viewName))
viewName = context.RouteData.GetRequiredString("action");
context.Controller.ViewData.Model = JsonConvert.DeserializeObject<ProfitDetailsmodel>(StringTools.Base64Decode(StringTools.Base64Decode(data)));
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
var viewContext = new ViewContext(context,
viewResult.View,
context.Controller.ViewData,
context.Controller.TempData,
sw);
try
{
viewResult.View.Render(viewContext, sw);
}
catch (Exception ex)
{
throw;
}
return sw.GetStringBuilder().ToString();
}
}
}
}
https://www.nuget.org/packages/Select.HtmlToPdf/
*请认真填写需求信息,我们会在24小时内与您取得联系。