如何在 blazor wasm 中创建供下载的 pdf
How can I create a pdf for download in blazor wasm
在 blazor wasm 中,我想创建一个 pdf 文件并使其可供下载。我测试了 pdfflow,但只能在控制台应用程序中实现 运行。有几种商业解决方案(devexpress、syncfusion),但它们非常昂贵。
接下来,我跨过了博客 post Generate PDF files using an html template and Playwright,这对我来说似乎很有希望。不幸的是,它不包含一个完整的示例,我无法做到 运行。这是我尝试过的:
我将 template.html 添加到 wwwroot 文件夹。
template.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="invoice.css">
</head>
<body style="padding: 3rem">
<h1>Invoice</h1>
Awesome company<br />
</body>
</html>
我添加了一个调用 CreatePdf()
的按钮。我从上面的 link 复制代码并根据我的需要修改它(因为例如没有提供方法 LoadOrder(orderId) )。
Index.razor
@page "/"
@using Scriban
@using System.IO
@using Microsoft.Playwright
@inject HttpClient Http
<button class="btn btn-primary" @onclick="CreatePdf">pdf</button>
@code{
private async Task CreatePdf()
{
//var templateContent = File.ReadAllText("template.html");
var templateContent = await Http.GetStringAsync("template.html");
var template = Template.Parse(templateContent);
//var templateData = new { Invoice = LoadOrder(orderId) };
//var pageContent = template.Render(templateData);
var pageContent = "testString";
//var dataUrl = "data:text/html;base64," + Convert.ToBase64String(Encoding.UTF8.GetBytes(pageContent));
var dataUrl = "data:text/html;base64," + pageContent;
我添加了以下两行,因为没有声明“浏览器”(Source from playwright)。
// Here, the app crashes.
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Webkit.LaunchAsync();
await using var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync(dataUrl, new PageGotoOptions { WaitUntil = WaitUntilState.NetworkIdle });
var output = await page.PdfAsync(new PagePdfOptions
{
Format = "A4",
Landscape = false,
});
await File.WriteAllBytesAsync("output.pdf", output);
} }
如何制作上面的代码运行?
您不能从浏览器 (js / wasm) 使用 Playwright。因此,您必须使用其他解决方案。例如,您可以使用 jsPDF。该库在将 html 转换为 pdf 时并不完美,但也许适合您的使用。
在 index.html
中添加一些脚本引用以使用 jsPDF(如果您愿意,也可以使用 npm 安装它们)
<script src="_framework/blazor.webassembly.js"></script>
<!-- jsPDF references -->
<script src="https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify@2.3.3/dist/purify.min.js"></script>
创建一个包含以下内容的文件wwwroot/HtmlToPdf.js
:
export function generateAndDownloadPdf(htmlOrElement, filename) {
const doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'a4'
});
return new Promise((resolve, reject) => {
doc.html(htmlOrElement, {
callback: doc => {
doc.save(filename);
resolve();
}
});
});
}
export function generatePdf(htmlOrElement) {
const doc = new jspdf.jsPDF();
return new Promise((resolve, reject) => {
doc.html(htmlOrElement, {
callback: doc => {
const output = doc.output("arraybuffer");
resolve(new Uint8Array(output));
}
});
});
}
然后,您可以使用 Razor 组件中的脚本:
@inject IJSRuntime JSRuntime
<button type="button" @onclick="DownloadPdf">Generate</button>
@code {
async Task DownloadPdf()
{
await using var module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./HtmlToPdf.js");
// Generate and download the PDF
await module.InvokeVoidAsync("generateAndDownloadPdf", "<h1>sample</h1>", "sample.pdf");
// Generate the PDF and get its content as byte[] (need .NET 6 to support Uint8Array)
var bytes = await module.InvokeAsync<byte[]>("generatePdf", "<h1>sample</h1>");
}
}
在 blazor wasm 中,我想创建一个 pdf 文件并使其可供下载。我测试了 pdfflow,但只能在控制台应用程序中实现 运行。有几种商业解决方案(devexpress、syncfusion),但它们非常昂贵。 接下来,我跨过了博客 post Generate PDF files using an html template and Playwright,这对我来说似乎很有希望。不幸的是,它不包含一个完整的示例,我无法做到 运行。这是我尝试过的: 我将 template.html 添加到 wwwroot 文件夹。
template.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="invoice.css">
</head>
<body style="padding: 3rem">
<h1>Invoice</h1>
Awesome company<br />
</body>
</html>
我添加了一个调用 CreatePdf()
的按钮。我从上面的 link 复制代码并根据我的需要修改它(因为例如没有提供方法 LoadOrder(orderId) )。
Index.razor
@page "/"
@using Scriban
@using System.IO
@using Microsoft.Playwright
@inject HttpClient Http
<button class="btn btn-primary" @onclick="CreatePdf">pdf</button>
@code{
private async Task CreatePdf()
{
//var templateContent = File.ReadAllText("template.html");
var templateContent = await Http.GetStringAsync("template.html");
var template = Template.Parse(templateContent);
//var templateData = new { Invoice = LoadOrder(orderId) };
//var pageContent = template.Render(templateData);
var pageContent = "testString";
//var dataUrl = "data:text/html;base64," + Convert.ToBase64String(Encoding.UTF8.GetBytes(pageContent));
var dataUrl = "data:text/html;base64," + pageContent;
我添加了以下两行,因为没有声明“浏览器”(Source from playwright)。
// Here, the app crashes.
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Webkit.LaunchAsync();
await using var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync(dataUrl, new PageGotoOptions { WaitUntil = WaitUntilState.NetworkIdle });
var output = await page.PdfAsync(new PagePdfOptions
{
Format = "A4",
Landscape = false,
});
await File.WriteAllBytesAsync("output.pdf", output);
} }
如何制作上面的代码运行?
您不能从浏览器 (js / wasm) 使用 Playwright。因此,您必须使用其他解决方案。例如,您可以使用 jsPDF。该库在将 html 转换为 pdf 时并不完美,但也许适合您的使用。
在 index.html
中添加一些脚本引用以使用 jsPDF(如果您愿意,也可以使用 npm 安装它们)
<script src="_framework/blazor.webassembly.js"></script>
<!-- jsPDF references -->
<script src="https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify@2.3.3/dist/purify.min.js"></script>
创建一个包含以下内容的文件wwwroot/HtmlToPdf.js
:
export function generateAndDownloadPdf(htmlOrElement, filename) {
const doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'a4'
});
return new Promise((resolve, reject) => {
doc.html(htmlOrElement, {
callback: doc => {
doc.save(filename);
resolve();
}
});
});
}
export function generatePdf(htmlOrElement) {
const doc = new jspdf.jsPDF();
return new Promise((resolve, reject) => {
doc.html(htmlOrElement, {
callback: doc => {
const output = doc.output("arraybuffer");
resolve(new Uint8Array(output));
}
});
});
}
然后,您可以使用 Razor 组件中的脚本:
@inject IJSRuntime JSRuntime
<button type="button" @onclick="DownloadPdf">Generate</button>
@code {
async Task DownloadPdf()
{
await using var module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./HtmlToPdf.js");
// Generate and download the PDF
await module.InvokeVoidAsync("generateAndDownloadPdf", "<h1>sample</h1>", "sample.pdf");
// Generate the PDF and get its content as byte[] (need .NET 6 to support Uint8Array)
var bytes = await module.InvokeAsync<byte[]>("generatePdf", "<h1>sample</h1>");
}
}