正文
现在有许多将html导出pdf的第三方包,这里介绍使用的是select.htmltopdf.netcore
使用select.htmltopdf.netcore
- 整体思路是将cshtml内容读出来,然后再转为pdf文档
- 读取cshtml内容有两种方法,第一种使用第三方包
razorengine.netcore,第二种使用官方方法进行读取。(注意两种方法的cshtml内容略有不同)
效果图展示
我把所有的源代码都上传到了我的个人github,有需要的请自取:github.com/weiming0803…

首先使用chatgpt生成个人简历信息

代码部分
homecontroller.cs :
public async task<iactionresult> topdf()
{
pdfdocument pdfdocument = new pdfdocument();
htmltopdf converter = new htmltopdf();//实例化一个html到pdf转换器对象
converter.options.pdfpageorientation = pdfpageorientation.portrait;//设置页面方向
converter.options.pdfpagesize = pdfpagesize.a4;//设置页面大小
converter.options.margintop = 10;//设置页边距
converter.options.marginbottom = 10;
converter.options.marginleft = 10;
converter.options.marginright = 10;
pdfreportmodel model = new pdfreportmodel { name = "彭于晏", email = "pengyuyan@outlook.com" };
//string htmlresult = readbyenginerazor(model);//第一种方法,使用razorengine.netcore读取cshtml文件
string htmlresult = await readcshtml(model);//第二种方法
if (!string.isnullorempty(htmlresult))
{
pdfdocument = converter.converthtmlstring(htmlresult);
}
string savepath = path.combine(environment.getfolderpath(environment.specialfolder.desktop), $@"exportpdf\{datetime.now.tostring("yyyymmdd")}");
directory.createdirectory(savepath);
string filename = path.combine(savepath, $"{datetime.now.tostring("yyyymmddhhmmssffff")}.pdf");
pdfdocument.save(filename);
byte[] bytes = system.io.file.readallbytes(filename);
return file(bytes, "application/pdf", path.getfilename(filename));
}
private string readbyenginerazor(pdfreportmodel model)
{
string template = system.io.file.readalltext("views/report/pdfreport.cshtml");
string htmlresult = engine.razor.runcompile(template, "pdfreport", typeof(pdfreportmodel), model);
return htmlresult;
}
private async task<string> readcshtml(pdfreportmodel model)
{
string htmlresult = await _viewrenderservice.rendertostringasync("report/pdfreport", model);
return htmlresult;
}
templategadgetprovider.cs :
public class templategadgetprovider
{
public static templategadgetprovider _instance;
public static templategadgetprovider instance
{
get
{
if (_instance == null)
_instance = new templategadgetprovider();
return _instance;
}
}
public string load(string virtualpath)
{
return file.readalltext(virtualpath);
}
}
pdfreport.css :
css样式文件:
html {
font-family: 'open sans', sans-serif;
background: whitesmoke;
}
a {
text-decoration: none;
color: black;
}
hr {
background: grey;
}
#container {
position: relative;
display: flex;
}
#profile {
flex: 15%;
display: block;
position: relative;
margin: 5% 2% 0 10%;
width: 100%;
height: 100%;
}
#info-cards {
flex: 55%;
display: block;
margin-top: 5%;
margin-right: 10%;
width: 100%;
height: 100%;
}
#image {
position: relative;
overflow: hidden;
}
#image,
#profile-photo {
position: relative;
width: 80px;
height: 80px;
border-radius: 10px;
}
#image > a {
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5) !important;
height: 100%;
width: 100%;
display: none;
}
#image > a > i {
-webkit-text-stroke: 1px #ffffffdd;
padding: 40%;
}
#image:hover a {
display: block;
}
#name {
font-size: 23px !important;
line-height: 20px !important;
}
#about,
.card > ul > li {
padding: 0 0 0 15px;
position: relative;
display: inline-block;
width: 100%;
}
#about {
font-size: 20px !important;
padding: 0 !important;
}
#name,
#about > p {
font-weight: bolder;
font-family: 'open sans', sans-serif;
}
#email {
font-size: 15px !important;
font-weight: bold !important;
font-family: 'cutive mono', monospace;
}
#college,
#email,
#year-graduation,
#education,
#more-about,
#telephone,
#fax {
color: #555;
font-size: 13.5px;
}
strong,
span {
color: black;
font-size: 16px;
}
#social-links,
#about {
display: inline-block;
}
#social-links {
margin-bottom: 12px;
}
#social-links a {
margin: 0 10px;
}
#edit-intro {
display: block;
color: #097bbf;
font-family: 'nunito', sans-serif;
}
.fab {
font-size: 1.1em;
}
.fab,
.fas {
color: whitesmoke;
}
#about > a {
top: 4px;
right: 8px;
}
.edit {
top: 19px;
right: 10px;
}
#about > a,
.edit {
position: absolute;
font-size: 15px !important;
}
.stroke-transparent {
-webkit-text-stroke: 1px #000;
-webkit-text-fill-color: transparent;
}
.blue {
color: #097bbf !important;
font-size: 13px;
}
.stroke-transparent-blue {
-webkit-text-stroke: 1px #097bbf;
-webkit-text-fill-color: transparent;
}
.card {
box-shadow: 0 3px 10px 0 rgba(0, 0, 0, .1);
overflow-x: hidden;
margin-bottom: 30px;
padding: 15px 30px 30px 30px;
background-color: #fff;
}
.card > p {
color: #0e141e;
font-weight: bolder;
font-size: 18px;
line-height: 2;
}
.card > p > i {
font-size: 18px;
}
.card > a {
font-weight: 400;
font-size: 15px;
margin: 0;
margin-left: 25px;
padding: 0;
border: 0;
height: auto;
background: transparent;
color: #097bbf;
outline: none;
cursor: pointer;
}
.card > ul {
list-style-type: none;
}
.tags {
font-size: 17px;
font-weight: bolder;
}
.tags ~ a {
display: none !important;
}
.tags span {
font-size: 14px;
font-weight: normal;
color: #0e141e;
}
.tags span span {
color: #738f93;
}
@media screen and (max-width:1090px) {
#profile {
margin-left: 5%;
}
}
@media screen and (max-width:850px) {
#container {
display: block;
}
#profile {
width: 90%;
}
.card {
margin: 0 5%;
margin-bottom: 30px;
}
}
pdfreport.cshtml :
使用
razorengine.netcore需要修改下面两处地方删除
@model pdfreportmodel将
@html.raw(@style)修改为@@raw(@style)
视图文件:点击查看详细内容
@using exportpdf.common
@model pdfreportmodel
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>document</title>
@{
string style = templategadgetprovider.instance.load(@"wwwroot\css\pdfreport.css");
}
<style>@html.raw(@style)</style>
</head>
<body>
<div id="inner-nav"></div>
<div id="container">
<div id="profile">
<div id="image">
<img id="profile-photo" src="https://img2023.cnblogs.com/blog/233608/202303/233608-20230308165653594-2049775608.jpg" alt="profile-image">
<a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><i class="fas fa-pen stroke-transparent"></i></a>
</div>
<p id="name">@model.name<br><span id="email">@model.email</span></p>
<p id="designation">前端开发工程师<br><span id="college">天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为也,所以动心忍性,增益其所不能。——《孟子》 </span></p>
<div id="social-links"><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><i class="fab fa-facebook-f stroke-transparent"></i></a><a><i
class="fab fa-twitter stroke-transparent"></i></a><a><i
class="fab fa-linkedin-in stroke-transparent"></i></a><a><i
class="fab fa-github stroke-transparent"></i></a></div>
<a id="edit-intro" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><i class="fas fa-pen-alt blue"></i> </a>
<hr width="100%">
<div id="about">
<p style="display:inline;">个人详情</p>
<a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><i class="fas fa-pen stroke-transparent-blue"></i></a>
</div>
<p id="year-graduation">预计毕业年份<br><strong>2023年6月</strong></p>
<p id="education">学历<br><strong>湖南大学 本科</strong></p>
<p id="more-about">专业<br><strong> 计算机科学与技术专业</strong></p>
<p id="telephone">电话<br><strong>0532-2271351</strong></p>
<p id="fax">传真<br><strong>+91-532-25453441</strong></p>
</div>
<div id="info-cards">
<div class="card">
<p><i class="fas fa-briefcase stroke-transparent"></i> 专业技能</p>
<ul>
<li>
<p class="tags">1. 熟练掌握html、css、javascript等前端基础技术</p>
</li>
<li>
<p class="tags">2. 熟悉jquery、bootstrap等常用前端框架和库</p>
</li>
<li>
<p class="tags">3. 了解node.js、express等后端开发技术</p>
</li>
<li>
<p class="tags">4. 掌握git、webpack等常用开发工具</p>
</li>
<li>
<p class="tags">5. 具备良好的编码风格和文档习惯</p>
</li>
</ul>
</div>
<div class="card">
<p><i class="fas fa-briefcase stroke-transparent"></i> 工作检验</p>
<ul>
<li>
<p class="tags">1. 依帆网站首页制作(个人项目)<br>
- 使用html、css、javascript实现了一个响应式的网站首页<br>
- 使用bootstrap进行布局和样式美化,使用jquery实现轮播图和导航栏效果<br>
- 使用webpack进行打包和优化,使用git进行版本控制和部署</p>
</li>
<li>
<p class="tags">2. 艺风网站后台管理系统(实习项目)<br>
- 参与了一个基于node.js和express的后台管理系统的开发<br>
- 负责前端页面的编写,使用ejs模板引擎渲染数据<br>
- 使用ajax和fetch进行数据交互,使用element ui组件库提升用户体验<br>
- 遵循mvc架构,使用mongoose操作mongodb数据库</p>
</li>
</ul>
</div>
<div class="card">
<p><i class="fas fa-graduation-cap stroke-transparent"></i> 自我评价</p>
<ul>
<li>
<p class="tags">具备较强的学习能力和逻辑思维能力,喜欢接触新技术和新知识</p>
</li>
<li>
<p class="tags">具备良好的沟通能力和团队协作能力,能够积极配合团队完成任务</p>
</li>
<li>
<p class="tags">具备一定的创新能力和解决问题能力,能够针对不同需求提出合理方案</p>
</li>
</ul>
<a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >+ add new</a>
</div>
</div>
</div>
</body>
</html>
viewrenderservice :
public class viewrenderservice
{
private readonly irazorviewengine _razorviewengine;
private readonly itempdataprovider _tempdataprovider;
private readonly iserviceprovider _serviceprovider;
public viewrenderservice(irazorviewengine razorviewengine,
itempdataprovider tempdataprovider,
iserviceprovider serviceprovider)
{
_razorviewengine = razorviewengine;
_tempdataprovider = tempdataprovider;
_serviceprovider = serviceprovider;
}
public async task<string> rendertostringasync(string viewname, object model)
{
var httpcontext = new defaulthttpcontext { requestservices = _serviceprovider };
var actioncontext = new actioncontext(httpcontext, new routedata(), new actiondescriptor());
using (var sw = new stringwriter())
{
var viewresult = _razorviewengine.findview(actioncontext, viewname, false);
if (viewresult.view == null)
{
throw new argumentnullexception($"{viewname} does not match any available view");
}
var viewdictionary = new viewdatadictionary(new emptymodelmetadataprovider(), new modelstatedictionary())
{
model = model
};
var viewcontext = new viewcontext(
actioncontext,
viewresult.view,
viewdictionary,
new tempdatadictionary(actioncontext.httpcontext, _tempdataprovider),
sw,
new htmlhelperoptions()
);
await viewresult.view.renderasync(viewcontext);
return sw.tostring();
}
}
}
program.cs :
builder.services.addtransient<viewrenderservice>();
以上就是使用select.htmltopdf.netcore将html导出为pdf的全部内容!
发表评论