0
0

PDF生成サンプル(Playwright)

Posted at

目的

動的な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の使い方がよくわかっていないので、このまま使うことにしました。)

ReportController.cs
        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に変換することができます。

ReportPdf.cs
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ファイルを生成します。

ReportController.cs
        [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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0