目的
動的なHTMLをPDFに変換する方法を検討し、その実現にはPlaywrightを使用することにしました。
Web API
インターフェースとしてはWebAPIを使用することにしました。
C#でのWebAPI作成を検討します。
現段階では、Visual Studioのテンプレートを利用することで開発労力を削減できると判断し、ASP.NETを選択しました。
HTMLの作成
まずは、入力したパラメータによってHTMLを生成する方法を検討します。
HTMLの生成には、Razorを使用することにしました。
Razorは、C#のコードをHTMLに埋め込むことができるテンプレートエンジンです。
使用に際しては、nugetパッケージのMicrosoft.AspNetCore.Mvc.Razorで検索して、インストールします。
ソース作成にはgithubのchatbotの提案ソースをほぼそのまま使っています。
(正直、Razorの使い方がよくわかっていないので、このまま使うことにしました。)
private async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
{
var viewResult = _viewEngine.FindView(ControllerContext, viewName, false);
if (viewResult.View == null)
{
throw new ArgumentNullException($"{viewName} does not match any available view");
}
using (var sw = new StringWriter())
{
var viewContext = new ViewContext(
ControllerContext,
viewResult.View,
new ViewDataDictionary<TModel>(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = model
},
new TempDataDictionary(ControllerContext.HttpContext, _tempDataProvider),
sw,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return sw.GetStringBuilder().ToString();
}
}
PDFの生成
HTMLをPDFに変換する方法を検討します。
HTMLをPDFに変換する方法はいくつかありますが、今回はPlaywrightを使用することにしました。
使用に際しては、nugetパッケージのMicrosoft.Playwrightで検索して、インストールします。
Playwrightは、ブラウザの自動操作を行うためのライブラリです。
Playwrightを使用することで、ブラウザを操作してHTMLをPDFに変換することができます。
using Microsoft.Playwright;
namespace net_pdf_sample.Models
{
public class ReportPdf
{
public string Content { get; set; } = string.Empty;
public string? HtmlFilePath { get; set; }
public string? PdfFilePath { get; set; }
private string _tempDirectory { get; set; }
// コンストラクタでテンポラリディレクトリのパスを受け取る
public ReportPdf(string tempDirectory)
{
_tempDirectory = tempDirectory;
}
// HTML文字列を受け取り、テンポラリディレクトリにHTMLファイルを作成する
public async Task<string> CreateHtmlFile(string htmlContent)
{
return await Task<string>.Run(() =>
{
var tempPath = Path.Combine(_tempDirectory, $"{Path.GetRandomFileName()}.html");
File.WriteAllText(tempPath, htmlContent);
HtmlFilePath = tempPath;
return tempPath;
});
}
// HTMLファイルをPDFに変換する
public async Task<string> ConvertToPdfAsync(string htmlFile)
{
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = true,
});
var pdfPath = Path.ChangeExtension(htmlFile, ".pdf");
var page = await browser.NewPageAsync();
await page.GotoAsync("file://" + htmlFile);
await page.PdfAsync(new PagePdfOptions
{
Path = pdfPath
});
PdfFilePath= pdfPath;
await browser.CloseAsync();
return pdfPath;
}
}
}
上記のコードは、WebAPIから特定のレポートを生成し、そのレポートをPDF形式で返すための処理を示しています。
この機能をWebAPIから利用するためのコードを実装します。
[HttpPost(Name = "Report")]
アトリビュートを使用してPOSTリクエストを受け取り、PostReport
メソッドはタイトルと任意の引数を受け取り、HTMLテンプレートをレンダリングしてPDFファイルを生成します。
[HttpPost(Name = "Report")]
public async Task<ActionResult<string>> PostReport(string title = "Title", string[]? args = null)
{
var report = new Models.Report()
{
Title = title,
Args = args
};
// テンプレートをViewでレンダリングしてHTML文字列を作成する
var html = await RenderViewToStringAsync("ReportTemplate", report);
var reportPdf = new Models.ReportPdf(_tempDirectoryProvider.DirectoryName);
var htmlFile = await reportPdf.CreateHtmlFile(html);
var pdfFile = await reportPdf.ConvertToPdfAsync(htmlFile);
return Ok(reportPdf);
}
まとめ
作成したソースコードはGitHubに登録しました。詳細は以下のリンクからご覧いただけます。
WebAPI_PDF_sample - github