Blazor Server でWeb画面やドキュメントを画像データに変換し、ダウンロードする機能を実装する場合、HTMLのテンプレートファイルを用意し、wkhtmltoimage で画像データに変換してからダウンロードするのがベターです。
ソースコードはGitHubで公開しています。
wkhtmltoimage について
wkhtmltoimage については Blazor Server で画像を作成しダウンロードする(on Windows) で説明済み。ここでは、Linuxで wkhtmltoimage を使う場合の手順を記載する。
1.インストール
1 2 3 4 |
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox-0.12.6-1.centos7.x86_64.rpm # rpm -Uvh wkhtmltox-0.12.6-1.centos7.x86_64.rpm |
2.バージョン確認
1 2 3 4 |
# wkhtmltopdf -V # wkhtmltoimage -V |
3.動作確認
1 2 3 4 |
# wkhtmltoimage https://google.co.jp out.jpg # wkhtmltoimage in.html out.jpg |
フォントについて
wkhtmltoimage が画像データを生成する際のフォントは、OSのフォントを使うので、画像変換するHTMLファイルに日本語が含まれている場合、Linuxに日本語フォントをインストールする必要がある。
IPAが公開している日本語フォントを使う場合
1 2 3 |
# yum install -y ipa-gothic-fonts ipa-pgothic-fonts ipa-mincho-fonts |
Windows の日本語フォントを使う場合
Windows 10 で標準となっている Segoeフォント を Linuxでも使いたい場合、Windows OS のフォントファイルを C:\Windows\Fonts フォルダからコピーし、Linux の /usr/local/share/fonts/ 配下に配置することで、Linuxでも Segoeフォント を使えるようになります。
参考=>LinuxでもMSフォントを使いWindowsでのスタイル崩れを予防
ソースコード構成
Blazor Server で画像を作成しダウンロードする(on Windows) をベースに、Linux側の画像データ生成処理を追加しています。
本番環境がLinuxでも、Windowsで開発する場合は Blazor Server で画像を作成しダウンロードする(on Windows) でデバッグすることになります。
ソースコード変更内容を解説
Util/WkHtmlToImage.cs
・Linux上で wkhtmltoimage コマンドを実行する為の共通部品。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace WebApplication1.Util { public static class WkHtmlToImage { public static void Exec(string fileNameIn, string fileNameOut) { var command = $"wkhtmltoimage {fileNameIn} {fileNameOut}"; using (var proc = new Process()) { proc.StartInfo.FileName = "/bin/bash"; proc.StartInfo.Arguments = "-c \" " + command + " \""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.Start(); proc.WaitForExit(); } } } } |
Pages/Counter.razor
・WindowsとLinuxで、画像変換処理が切り替わるように分岐を追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
@page "/counter" @using CoreHtmlToImage @inject IJSRuntime JS <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> <br> <br> <button class="btn btn-primary" @onclick="DownloadFileExec_Image">Image file download</button> @code { private int currentCount = 0; private static HtmlConverter _HtmlConverter = new HtmlConverter(); private void IncrementCount() { currentCount++; } private async Task DownloadFileExec_Image() { var html = string.Format(TemplateData.CounterHtml, TemplateData.StyleCSS, currentCount); byte[] imageData; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { imageData = _HtmlConverter.FromHtmlString(html, 800, ImageFormat.Jpg, 100); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var inHtmlFileName = Path.GetTempFileName().Replace(".tmp", ".html"); var outImageFileName = Path.GetTempFileName().Replace(".tmp", ".jpg"); File.WriteAllText(inHtmlFileName, html); WkHtmlToImage.Exec(inHtmlFileName, outImageFileName); imageData = File.ReadAllBytes(outImageFileName); File.Delete(inHtmlFileName); File.Delete(outImageFileName); } else { throw new NotImplementedException(); } var filename = "Counter.jpg"; await JS.InvokeVoidAsync("saveAsFile", filename, Convert.ToBase64String(imageData)); } } |
_Imports.razor
・参照を追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@using System.Net.Http @using System.IO @using System.Text @using System.Runtime.InteropServices @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using WebApplication1 @using WebApplication1.Shared @using WebApplication1.SharedData @using WebApplication1.Util |
コメント