背景
之前打印时将Html链接直接返回给打印插件,由打印插件进行Html解析和转换成PDF。由于接口变动,现在需要业务系统直接返回PDF内容。考虑到MVC模式的C–>V,需要传递参数后才能形成完整的Html,遂想到后台直接获取View()内容,并将其转换为Byte[],返回 FileContentResult(pdfByte, “application/pdf”),可直接在浏览器访问链接查看PDF。
代码展示
下边是后台的调用入口
[AccessPrivilege(Type = AccessPrivilegeType.Anonymous)]
public FileContentResult QrCodePrint(string refid)
{
try
{
var report = RequestedProcedureService.GetById(refid);
//需要给ViewData.Model传入页面需要的数据模型
ViewData.Model = report;
var htmlText = ViewPdf("QrCodePrint", "_Layout");
byte[] pdfByte = SelectPdfConvert(htmlText);
return new FileContentResult(pdfByte, "application/pdf");
}
catch (Exception e)
{
Logger.Error(e.Message + "xxxxx失败");
return null;
}
}
#region HtmlToPdf
//通过后台拿到View层的Html页面并转成String
private string RenderViewToString(Controller controller, string viewName, string masterName)
{
IView view = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, masterName).View;
using (StringWriter writer = new StringWriter())
{
ViewContext viewContext = new ViewContext(controller.ControllerContext, view, controller.ViewData,
controller.TempData, writer);
viewContext.View.Render(viewContext, writer);
return writer.ToString();
}
}
/// <summary>
///
/// </summary>
/// <param name="viewName">当前页面的名字(和Controller名字相同)</param>
/// <param name="masterName">父级页面名称(默认是"_Layout")</param>
/// <returns></returns>
private string ViewPdf(string viewName, string masterName)
{
// Render the view html to a string.
string htmlText = RenderViewToString(this, viewName, masterName);
return htmlText;
}
//Select.HtmlToPdf
private byte[] SelectPdfConvert(string html)
{
byte[] res = null;
using (MemoryStream ms = new MemoryStream()) {
SelectPdf.HtmlToPdf converter = new SelectPdf.HtmlToPdf();
PdfDocument doc = new PdfDocument();
var docStr = converter.ConvertHtmlString(html);
doc.Append(docStr);
//doc.Save可以传入文件路径如:xx.pdf。在此需要返回byte,所以写入到MemoryStream中
doc.Save(ms);
res = ms.ToArray();
doc.Close();
}
return res;
}
#endregion
Html页面内容(Model为后台传入的参数):
<!DOCTYPE html>
@{
Layout = null;
var locationName = Model.LocationName;
var patientName = Model.PatientName;
var patientId = Model.PatientId;
var modalityType = Model.ModalityType_Name;
var startTime = Model.StartTime;
var qrCode = Model.QrCode;
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<div style="float: left;">
<div id="location">@locationName</div>
<div id="patientId">@patientId</div>
<div id="patientName">@patientName</div>
<div id="modalityType">@modalityType</div>
<div id="startTime">@startTime</div>
<div style="font-size: xx-small;">请用手机扫描二维码</div>
<div style="font-size: xx-small;">查看本次检查的影像和报告</div>
</div>
<img src="data:image/png;base64,@qrCode" style="height: 100px; width: 100px;"/>
</body>
</html>
访问效果如下:
过程总结:
-
获取View层的Html过程中,出错的地方有:ViewName,masterName和ViewData的传入(ViewData需要在后台传入,见代码)
参考的资料:
https://www.cnblogs.com/LD13/articles/LD13_1001.html -
Html内容Text转PDF过程遇到的问题:
(1)使用HtmlRender和HtmlRender.PdfSharp碰到的问题:中文字体无法显示。找了很多资料,无果。
(2)使用ITextSharp碰到的问题:对Html内容语法检查较为严格,对于复杂的页面不友好。
(3)使用Select.HtmlToPdf,解决问题,且调用简单。
参考资料地址: https://blog.csdn.net/qq_40677590/article/details/102874012