跳转到内容
搜索文档

使用 HTML 和 CSS 生成 PDF

最后更新 查看 MarkdownAgent 设置

部署 Browser Run Worker 指南所示,Browser Run 可用于为任意给定 URL 生成屏幕截图。除屏幕截图外,你还可以为给定网页生成完整 PDF 文档,也可以自行提供网页 markup 和样式。

你可以通过两种方式使用 Browser Run 生成 PDF:

  • Quick Actions:使用 /pdf 端点。如果你不需要自定义渲染行为,这是理想选择。
  • PuppeteerPlaywright:在 Workers 中使用浏览器自动化,以获得额外的控制和自定义能力。

选择最适合你用例的方式。

以下示例展示如何使用 Puppeteer 生成 PDF。

前提条件

  1. 使用 create-cloudflare CLI 生成新的 Hello World Cloudflare Worker 脚本:
npm create cloudflare@latest -- browser-worker
  1. 安装 @cloudflare/puppeteer,以便控制 Browser Run 实例:
npm i -D @cloudflare/puppeteer
  1. 在新的 Wrangler 配置中添加 Browser Run 绑定:
{
	"browser": {
		"binding": "BROWSER",
	},
}
[browser]
binding = "BROWSER"
  1. src/index.ts(JavaScript 项目为 src/index.js)的内容替换为以下骨架脚本:
import puppeteer from "@cloudflare/puppeteer";

const generateDocument = (name: string) => {};

export default {
	async fetch(request, env) {
		const { searchParams } = new URL(request.url);
		let name = searchParams.get("name");

		if (!name) {
			return new Response("Please provide a name using the ?name= parameter");
		}

		const browser = await puppeteer.launch(env.BROWSER);
		const page = await browser.newPage();

		// Step 1: Define HTML and CSS
		const document = generateDocument(name);

		// Step 2: Send HTML and CSS to our browser
		await page.setContent(document);

		// Step 3: Generate and return PDF

		return new Response();
	},
};

1. 定义 HTML 和 CSS

与其使用 Browser Run 导航到用户提供的 URL,不如手动生成网页,然后将该网页提供给 Browser Run 实例。这允许你渲染任何你想要的设计。

在本示例中,我们将接收用户提供的 content(通过 ?name= 参数),并在最终 PDF 文档中输出该名称。

首先,用以下内容填充 generateDocument 函数:

const generateDocument = (name: string) => {
	return `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <style>
      html,
      body,
      #container {
        width: 100%;
        height: 100%;
        margin: 0;
      }
      body {
        font-family: Baskerville, Georgia, Times, serif;
        background-color: #f7f1dc;
      }
      strong {
        color: #5c594f;
        font-size: 128px;
        margin: 32px 0 48px 0;
      }
      em {
        font-size: 24px;
      }
      #container {
        flex-direction: column;
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
      }
    </style>
  </head>

  <body>
    <div id="container">
      <em>This is to certify that</em>
      <strong>${name}</strong>
      <em>has rendered a PDF using Cloudflare Workers</em>
    </div>
  </body>
</html>
`;
};

此 HTML 文档应渲染米色背景,模仿证书样式,显示用户提供的名称已成功使用 Cloudflare Workers 渲染 PDF。

2. 将 HTML 和 CSS 加载到浏览器

现在你有了完整样式的 HTML 文档,可以获取内容并发送到浏览器实例。按如下方式创建空页面以存储此文档:

const browser = await puppeteer.launch(env.BROWSER);
const page = await browser.newPage();

然后可以使用 page.setContent() 函数从字符串设置页面的 HTML 内容,因此可以直接传入创建的文档:

await page.setContent(document);

3. 生成并返回 PDF

Browser Run 实例现在渲染你提供的 HTML 和 CSS,你可以使用 page.pdf() 命令生成 PDF 文件并返回给客户端。

let pdf = page.pdf({ printBackground: true });

page.pdf() 调用支持多种选项,包括将生成 PDF 的尺寸设置为特定纸张大小、设置特定边距以及允许完全透明背景。目前,你仅覆盖 printBackground 选项以允许 body 背景样式显示。

现在你有了 PDF 数据,在 Response 中以 application/pdf content type 返回:

return new Response(pdf, {
	headers: {
		"content-type": "application/pdf",
	},
});

总结

完整的 Worker 脚本现如下所示:

import puppeteer from "@cloudflare/puppeteer";

const generateDocument = (name: string) => {
	return `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <style>
	  html, body, #container {
		width: 100%;
	    height: 100%;
		margin: 0;
	  }
      body {
        font-family: Baskerville, Georgia, Times, serif;
        background-color: #f7f1dc;
      }
      strong {
        color: #5c594f;
		font-size: 128px;
		margin: 32px 0 48px 0;
      }
	  em {
		font-size: 24px;
	  }
      #container {
		flex-direction: column;
        display: flex;
        align-items: center;
        justify-content: center;
		text-align: center
      }
    </style>
  </head>

  <body>
    <div id="container">
		<em>This is to certify that</em>
		<strong>${name}</strong>
		<em>has rendered a PDF using Cloudflare Workers</em>
	</div>
  </body>
</html>
`;
};

export default {
	async fetch(request, env) {
		const { searchParams } = new URL(request.url);
		let name = searchParams.get("name");

		if (!name) {
			return new Response("Please provide a name using the ?name= parameter");
		}

		const browser = await puppeteer.launch(env.BROWSER);
		const page = await browser.newPage();

		// Step 1: Define HTML and CSS
		const document = generateDocument(name);

		// // Step 2: Send HTML and CSS to our browser
		await page.setContent(document);

		// // Step 3: Generate and return PDF
		const pdf = await page.pdf({ printBackground: true });

		// Close browser since we no longer need it
		await browser.close();

		return new Response(pdf, {
			headers: {
				"content-type": "application/pdf",
			},
		});
	},
};

你可以通过以下方式运行此脚本进行测试:

npx wrangler dev

脚本运行后,你可以向本地 URL 传递 ?name 参数(例如 http://localhost:8787/?name=Harley),应该会看到以下内容:

生成的 PDF 截图,模拟证书上显示了作者姓名。.


自定义字体

如果你的 PDF 需要 Browser Run 环境中未预装的字体,可以使用 addStyleTag 加载自定义字体。这允许你在生成 PDF 之前从 CDN 注入字体或将其嵌入为 Base64 字符串。

有关说明和示例,请参阅使用自定义字体


动态生成 PDF 文档解决了许多常见用例,从向客户开具发票到归档文档,再到创建动态证书(如本简单示例所示)。

这篇文档对您有帮助吗?