97 lines
3.2 KiB
C#
97 lines
3.2 KiB
C#
using System.IO;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using Microsoft.Web.WebView2.Core;
|
|
using Microsoft.Web.WebView2.Wpf;
|
|
using YY.Admin.Core.Util;
|
|
|
|
namespace YY.Admin.Infrastructure.Print;
|
|
|
|
/// <summary>
|
|
/// 使用隐藏 WebView2 窗口将 HTML 字符串渲染为 PDF base64。
|
|
/// 所有调用必须最终在 WPF UI 线程执行,由内部 Dispatcher 保证。
|
|
/// </summary>
|
|
public static class HtmlToPdfRenderer
|
|
{
|
|
public static Task<string> RenderAsync(string html, double widthMm = 210, double heightMm = 297)
|
|
{
|
|
var tcs = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
Application.Current.Dispatcher.InvokeAsync(async () =>
|
|
{
|
|
try
|
|
{
|
|
var result = await RenderOnUiThreadAsync(html, widthMm, heightMm);
|
|
tcs.SetResult(result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
tcs.SetException(ex);
|
|
}
|
|
});
|
|
|
|
return tcs.Task;
|
|
}
|
|
|
|
private static async Task<string> RenderOnUiThreadAsync(string html, double widthMm, double heightMm)
|
|
{
|
|
var tempHtml = Path.ChangeExtension(Path.GetTempFileName(), ".html");
|
|
var tempPdf = Path.ChangeExtension(Path.GetTempFileName(), ".pdf");
|
|
Window? win = null;
|
|
|
|
try
|
|
{
|
|
File.WriteAllText(tempHtml, html, Encoding.UTF8);
|
|
|
|
var userData = AppWritablePaths.EnsureDirectoryExists(
|
|
Path.Combine(AppWritablePaths.LocalApplicationRoot, "WebView2", "HtmlToPdf"));
|
|
var env = await CoreWebView2Environment.CreateAsync(browserExecutableFolder: null, userDataFolder: userData);
|
|
var wv = new WebView2();
|
|
|
|
win = new Window
|
|
{
|
|
Width = 1,
|
|
Height = 1,
|
|
Left = -99999,
|
|
Top = -99999,
|
|
ShowInTaskbar = false,
|
|
WindowStyle = WindowStyle.None,
|
|
Visibility = Visibility.Visible
|
|
};
|
|
win.Content = wv;
|
|
win.Show();
|
|
|
|
await wv.EnsureCoreWebView2Async(env);
|
|
|
|
var navTcs = new TaskCompletionSource();
|
|
wv.CoreWebView2.NavigationCompleted += (_, _) => navTcs.TrySetResult();
|
|
wv.CoreWebView2.Navigate(new Uri(tempHtml).AbsoluteUri);
|
|
await navTcs.Task;
|
|
|
|
// 短暂等待 JS/CSS 完成渲染
|
|
await Task.Delay(200);
|
|
|
|
var settings = env.CreatePrintSettings();
|
|
settings.PageWidth = widthMm / 25.4;
|
|
settings.PageHeight = heightMm / 25.4;
|
|
settings.MarginTop = 0;
|
|
settings.MarginBottom = 0;
|
|
settings.MarginLeft = 0;
|
|
settings.MarginRight = 0;
|
|
settings.ShouldPrintHeaderAndFooter = false;
|
|
settings.ShouldPrintBackgrounds = true;
|
|
|
|
await wv.CoreWebView2.PrintToPdfAsync(tempPdf, settings);
|
|
|
|
var pdfBytes = File.ReadAllBytes(tempPdf);
|
|
return Convert.ToBase64String(pdfBytes);
|
|
}
|
|
finally
|
|
{
|
|
win?.Close();
|
|
try { File.Delete(tempHtml); } catch { }
|
|
try { File.Delete(tempPdf); } catch { }
|
|
}
|
|
}
|
|
}
|