1723173439
2024-08-08 16:21:38
社内および社外のユーザーがコンテンツを PDF 形式で印刷する必要があるユース ケースがいくつかあります。この機能は、DXP Web アプリから Docker コンテナーで実行されている Azure Function App にオフロードされています。Syncfusion .Net PDF Framework (注: サブスクリプションが必要) を使用します。最初のユース ケースでは、印刷用のエンドポイントに URL を提供できます。2 番目のユース ケースでは、XHTML コンテンツの配列をエンドポイントに POST します。
Azure Function App を作成する
Visual Studio で新しいプロジェクトを作成し、Azure Functions を選択します。
プロジェクトに名前を付ける

ここではデフォルトを使用します:
- .Net 8 分離 バージョン
- HTTP トリガー 関数ではGETとPOSTを使用するため
- コンテナサポートを有効にする Dockerを活用するため
- 関数 承認レベルを設定すると、ファンクション キーが必要になります。(この承認レベルで Azure にホストされている場合、エンドポイントにアクセスするためにファンクション キーが必要になります。)
「作成」をクリックします。

これにより、基本的な足場が得られます。

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
namespace TestPdfEndpoint
{
public class Function1
{
private readonly ILogger _logger;
public Function1(ILogger logger)
{
_logger = logger;
}
[Function("Function1")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
return new OkObjectResult("Welcome to Azure Functions!");
}
}
}
ConvertUrlToPdf関数を追加する
Function1 の名前を ConvertUrlToPdf に変更します。
public class ConvertUrlToPdf
{
private readonly ILogger _logger;
public ConvertUrlToPdf(ILogger logger)
{
_logger = logger;
}
[Function("ConvertUrlToPdf")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
return new OkObjectResult("Welcome to Azure Functions!");
}
}
IActionResult を非同期タスクに変更し、FunctionContext パラメータを追加します。
public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req, FunctionContext functionContext)
Syncfusion.HtmlToPdfConverter.Net.Linux nuget パッケージを追加します。関数アプリは Linux でホストされます。このパッケージは、URL を PDF ファイルに変換するという面倒な作業を実行します。nuget には、Blink ヘッドレス Chrome ブラウザが含まれています。
クエリ文字列パラメータとして関数に URL を渡すので、リクエストに「URL」パラメータがあるかどうかを確認します。見つからない場合は EmptyResult を返します。
string urlString = req.Query["url"];
//return if no url
if (string.IsNullOrEmpty(urlString))
{
return new EmptyResult();
}
Blink バイナリへのパスを取得します。これは、後で設定オブジェクトで必要になります。
var directory = Directory.GetCurrentDirectory();
var blinkBinariesPath = Path.Combine(directory, "runtimes/linux/native");
HTML から PDF へのコンバーターを初期化します。
//Initialize the HTML to PDF converter with the Blink rendering engine.
var htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.Blink)
{
ConverterSettings = null,
ReuseBrowserProcess = false
};
設定オブジェクトを作成し、値を設定します。これらのコマンド ライン引数設定は、Syncfusion のドキュメントから取得されます。
var settings = new BlinkConverterSettings();
//Set command line arguments to run without sandbox.
settings.CommandLineArguments.Add("--no-sandbox");
settings.CommandLineArguments.Add("--disable-setuid-sandbox");
settings.BlinkPath = blinkBinariesPath;
設定オブジェクトを割り当てます。
//Assign WebKit settings to the HTML converter
htmlConverter.ConverterSettings = settings;
URL をコンバーターに渡します。出力ストリームに保存します。
var newDocument = htmlConverter.Convert(urlString);
var ms = new MemoryStream();
newDocument.Save(ms);
newDocument.Close();
ms.Position = 0;
MemoryStream から FileStreamResult を返します。コンテンツ タイプとファイル名を指定します。
return new FileStreamResult(ms, "application/pdf")
{
FileDownloadName = "Test.pdf"
};
この時点で、関数は次のようになります。
public class ConvertUrlToPdf
{
private readonly ILogger _logger;
public ConvertUrlToPdf(ILogger logger)
{
_logger = logger;
}
[Function("ConvertUrlToPdf")]
public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req, FunctionContext functionContext)
{
string urlString = req.Query["url"];
//return if no url
if (string.IsNullOrEmpty(urlString))
{
return new EmptyResult();
}
var directory = Directory.GetCurrentDirectory();
var blinkBinariesPath = Path.Combine(directory, "runtimes/linux/native");
//Initialize the HTML to PDF converter with the Blink rendering engine.
var htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.Blink)
{
ConverterSettings = null,
ReuseBrowserProcess = false
};
var settings = new BlinkConverterSettings();
//Set command line arguments to run without sandbox.
settings.CommandLineArguments.Add("--no-sandbox");
settings.CommandLineArguments.Add("--disable-setuid-sandbox");
settings.BlinkPath = blinkBinariesPath;
//Assign WebKit settings to the HTML converter
htmlConverter.ConverterSettings = settings;
var newDocument = htmlConverter.Convert(urlString);
var ms = new MemoryStream();
newDocument.Save(ms);
newDocument.Close();
ms.Position = 0;
return new FileStreamResult(ms, "application/pdf")
{
FileDownloadName = "Test.pdf"
};
}
}
追加のクエリ文字列パラメータを追加して、方向、高さ、幅、出力ファイル名など、PDF 出力のあらゆる側面を制御できます。
string orientation = req.Query["orientation"];
string widthString = req.Query["width"];
string heightString = req.Query["height"];
string fileName = req.Query["filename"];
int.TryParse(widthString, out int width);
int.TryParse(heightString, out var height);
if (width == 0)
{
width = 817;
}
if (!string.IsNullOrEmpty(orientation) && orientation.ToLower().Equals("landscape"))
settings.Orientation = PdfPageOrientation.Landscape;
settings.BlinkPath = blinkBinariesPath;
settings.Margin.All = 0;
settings.ViewPortSize = new Size(width, height);
Dockerfileの更新
Syncfusion にはいくつかの基本的な要件があるため、Dockerfile に以下を追加する必要があります (Syncfusion のドキュメントを参照)。
RUN apt-get update &&
apt-get install -yq --no-install-recommends
libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1
libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6
libnss3 libgbm1
完全な Dockerfile は次のようになります。
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0 AS base
RUN apt-get update &&
apt-get install -yq --no-install-recommends
libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1
libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6
libnss3 libgbm1
WORKDIR /home/site/wwwroot
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["TestPdfEndpoint.csproj", "."]
RUN dotnet restore "./TestPdfEndpoint.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "./TestPdfEndpoint.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./TestPdfEndpoint.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /home/site/wwwroot
COPY --from=publish /app/publish .
ENV AzureWebJobsScriptRoot=/home/site/wwwroot
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
PrintUrlToPdf エンドポイントのテスト
Docker Desktop を使用してコンテナーを起動します。ブラウザーまたは Postman を使用して PDF 生成をテストできます。クエリ文字列に、印刷するサイトの URL を追加します。

ConvertToPdf関数を追加する
2 番目の関数は、主に最初の関数をコピーして貼り付け、いくつかの調整を加えたものです。
この関数では、POST された Xhtmlstring の配列を検索します。
req.Form.TryGetValue("html", out var strings);
次に、それぞれにストリームを作成します。
var streams = new Stream[strings.Count];
for (var i = 0; i
GetMemoryStream は次のようになります。
private static MemoryStream GetMemoryStream(string url, HtmlToPdfConverter htmlConverter)
{
try
{
PdfDocument newDocument = htmlConverter.Convert(url, string.Empty);
var ms = new MemoryStream();
newDocument.Save(ms);
newDocument.Close();
ms.Position = 0;
return ms;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
結合されたコンテンツを保持する新しい PdfDocument を作成します。
var mergedDocument = new PdfDocument
{
EnableMemoryOptimization = true
};
ストリームを PdfDocument に追加します。
PdfDocumentBase.Merge(mergedDocument, streams);
//Save the document into stream.
var stream = new MemoryStream();
mergedDocument.Save(stream);
//Close the document.
mergedDocument.Close(true);
//Disposes the streams.
foreach (var memStream in streams)
{
await memStream.DisposeAsync();
}
stream.Position = 0;
最後に、FileStreamResult を返します。
return new FileStreamResult(stream, "application/pdf")
{
FileDownloadName = "TestMergedPdf.pdf"
};
ConvertToPdf の最終バージョンは次のとおりです。
public class ConvertToPdf
{
private readonly ILogger _logger;
public ConvertToPdf(ILogger logger)
{
_logger = logger;
}
[Function("ConvertToPdf")]
public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
req.Form.TryGetValue("html", out var strings);
var directory = Directory.GetCurrentDirectory();
var blinkBinariesPath = Path.Combine(directory, "runtimes/linux/native");
//Initialize the HTML to PDF converter with the Blink rendering engine.
var htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.Blink)
{
ConverterSettings = null,
ReuseBrowserProcess = false
};
var settings = new BlinkConverterSettings();
//Set command line arguments to run without sandbox.
settings.CommandLineArguments.Add("--no-sandbox");
settings.CommandLineArguments.Add("--disable-setuid-sandbox");
settings.BlinkPath = blinkBinariesPath;
//Assign WebKit settings to the HTML converter
htmlConverter.ConverterSettings = settings;
var streams = new Stream[strings.Count];
for (var i = 0; i
ConvertToPdf エンドポイントのテスト
Docker Desktop を使用してコンテナを起動します。Postman を使用してテストします。エンドポイントに POST して、複数の「HTML」キーと値のペアを提供します。PDF のページごとに 1 つずつです。

Optimizely Webアプリに結び付ける
エンドポイントができたので、特定の URL または POST コンテンツを印刷するためのリンクを提供できます。
注記
実稼働環境で使用する場合は、ライセンスを購入してアプリに提供する必要があります。
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("XXX...");
Azure での Function の設定はこの記事の範囲外ですが、今後の記事で取り上げる予定です。
2024年8月8日
#Syncfusion #.Net #PDF #Fram #を使用した #PDF #作成用の #Azure #Function #App