本文探讨了如何在ABP框架中使用TPL文件将HTML模板转换为PDF文档.了解这种强大的方法如何简化文档创建,使开发人员能够高效地生成高质量的 PDF。和我一起演练利用 TPL 文件增强应用程序文档生成功能的步骤和最佳实践。
场景我们的系统中有广告。当我们的广告获得管理员的批准后,我们将发送已批准的广告报告并发送邮件以获取信息。
注意: 我将使用 Puppeteer Sharp 库生成 pdf。
广告批准报告 TPL 文件部分<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>{{ L "AdvertApprovedReport" }}</title></head><body><div }}: €{{ model.expected_total }}</div></div></body></html>我们需要在派生自 TemplateDefinitionProvider 的类中声明这一点。
public AdvertEmailTemplateDefinitionProvider : TemplateDefinitionProvider { public override void Define(ITemplateDefinitionContext context) { context.Add( new TemplateDefinition( AdvertEmailTemplates.AdvertApprovedReportBody, displayName: LocalizableString.Create\<KhanPalettenResource>( $"TextTemplate:{AdvertEmailTemplates.AdvertApprovedReport}" ), layout: StandardEmailTemplates.Layout, localizationResource: typeof(KhanPalettenResource) ).WithVirtualFilePath("/Adverts/Templates/AdvertApprovedReport.tpl", true) ); } } public AdvertEmailTemplates { public const string AdvertApprovedReport = "AdvertApprovedReport"; }电子邮件运营部分 public async Task SendAdvertReportAsync(Advert advert,List<string> customerMails,List<string> adminMails ) {var attachmentModel = new { warehouse_name = advert?.Warehouse?.Name ?? string.Empty, warehouse_postal_code = advert?.Warehouse?.PostalCode?.Code ?? string.Empty, warehouse_place = advert?.Warehouse?.Place?.Name ?? string.Empty, warehouse_country = advert?.Warehouse?.Country?.Name ?? string.Empty, advert_code = advert?.TransactionNumber ?? string.Empty, approve_date = DateTime.Now.ToString("dd.MM.yyyy HH:mm"), advert_items = advert?.Items?.Select(x => new { product_name = x?.Product?.Name ?? string.Empty, quantity = x?.Quantity ?? 0, total_cost = x?.TotalCost ?? 0m, unit_price = x?.UnitPrice ?? 0m, }) ?? Enumerable.Empty<object>(), approved_advert_items = advert?.ApprovedItems?.Select(x => new { product_name = x?.Product?.Name ?? string.Empty, quantity = x?.Quantity ?? 0, total_cost = x?.TotalCost ?? 0m, unit_price = x?.UnitPrice ?? 0m, }) ?? Enumerable.Empty<object>(), subtotal = advert?.ApprovedItems?.Sum(x => x.TotalCost) ?? 0m, freight_price = advert?.TransportationPrice?.Price ?? 0m, service_fee = advert?.ApprovedItems?.Sum(x => x.Quantity * x.ServiceFees.Sum(fee => fee.ServicePrice.Price) ) ?? 0m, expected_total = (advert?.ApprovedItems?.Sum(x => x.TotalCost) ?? 0m) - (advert?.TransportationPrice?.Price ?? 0m) - ( advert?.ApprovedItems?.Sum(x => x.Quantity * x.ServiceFees.Sum(fee => fee.ServicePrice.Price) ) ?? 0m ) };var emailAttachmentContent = await _templateRenderer.RenderAsync( AdvertEmailTemplates.AdvertApprovedReport, attachmentModel );byte[] pdfBytes = await _pdfService.ConvertHtmlToPdf(emailAttachmentContent);var mailMessage = new MailMessage { Subject = _stringLocalizer["AdvertApprovedReport"], IsBodyHtml = true, Body = emailBodyContent, };foreach (var customer in customerMails) { mailMessage.To.Add(customer); }// from our code the scenario was like this:)foreach (var admin in adminMails) { mailMessage.Bcc.Add(admin); } mailMessage.Attachments.Add(new Attachment(new MemoryStream(pdfBytes), "AdvertApprovedReport.pdf", "application/pdf") );await _emailSender.SendAsync(mailMessage); }工作部分public SendAdvertApprovedInfoLinkJob : AsyncBackgroundJob<SendAdvertApprovedInfoLinkArgs>,ITransientDependency{private readonly IAdvertRepository _advertRepository;private readonly IAdvertEmailer _advertEmailer;public SendAdvertApprovedInfoLinkJob(IAdvertRepository advertRepository,IAdvertEmailer advertEmailer ) { _advertRepository = advertRepository; _advertEmailer = advertEmailer; }public override async Task ExecuteAsync(SendAdvertApprovedInfoLinkArgs args) {var advert = await _advertRepository.GetAsync(args.AdvertId);var ownerEmail = advert .Company.Members.Where(x => x.IsOwner) .Select(x => x.User.Email) .FirstOrDefault(); Check.NotOrEmpty(ownerEmail, nameof(ownerEmail));await _advertEmailer.SendAdvertApprovedInfoLinkAsync(ownerEmail, args.TransactionNumber); }}Pdf转换部分 public PdfService : IPdfService {public async Task<byte[]> ConvertHtmlToPdf(string htmlContent) {await new BrowserFetcher().DownloadAsync();using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true, Args = ["--no-sandbox"] } ) )using (var page = await browser.NewPageAsync()) {await page.SetContentAsync(htmlContent);var pdfBytes = await page.PdfDataAsync();return pdfBytes; } } }让我们调用我们的方法 [HttpPut("/api/app/advert-approval/{id}/{approvedItemId}")]public async Task<AdvertDto> UpdateAsync(Guid id,long approvedItemId,UpdateAdvertItemDto input ) {var advert = await _advertRepository.GetAsync(id);var item = advert.GetApprovedItem(approvedItemId); item.SetQuantity(input.Quantity);var advertManager = GetAdvertManager(advert.AppModule);await advertManager.CalculateTotalCost(advert);await _advertRepository.UpdateAsync(advert);await _backgroundJobManager.EnqueueAsync(new SendAdvertReportArgs(advert.Id));return ObjectMapper.MapToDto(advert); }在这里,当我们更新广告状态时,我们称之为电子邮件发送部分。
pdf文件截图:这就是我要分享的关于这个话题的全部内容。我希望这篇文章对每个人都有信息和富有成效。
如果你喜欢我的文章,请给我一个赞!谢谢