【发布时间】:2021-09-25 17:01:54
【问题描述】:
这是我第一次测试 Next.js API,我对整个 Next.js/React 世界也很陌生,所以请多多包涵。
此 API 路由的目标是触发自动下载带有自定义水印的 PDF,该水印由 API URL 查询参数生成,如下所示:/api/PDFWatermark?id=123&firstname=John&lastname=Doe
为了创建水印,我使用pdf-lib 和this 代码的修改版本来为我的PDF 添加水印。为了生成原始 PDF pdfDoc 的修改和可下载版本,我尝试使用 pdfBytesafter 水印创建一个 blob。创建 Blob 后,我想我可以将其添加到附加到 DOM 的锚点中。
注释掉blob和anchor代码时,出现两个错误:
- ReferenceError: Blob 未定义
- ReferenceError: document is not defined(可能是因为没有 DOM 来附加锚链接)
此时我只能将pdfBytes 打印为 json,我无法创建和下载实际带水印的 PDF 文件。
有没有办法在调用 API 时将pdfBytes 自动下载为 PDF 文件?
更新
更改 modifyPDF 以返回缓冲区后的工作代码如下:
const pdfBytes = await pdfDoc.save();
return Buffer.from(pdfBytes.buffer, 'binary');
还有:
export default async function handler(req, res) {
const filename = "test.pdf";
const {id, firstname, lastname} = req.query;
const pdfBuffer = await modifyPDF(firstname, lastname, id);
res.status(200);
res.setHeader('Content-Type', 'application/pdf'); // Displsay
res.setHeader('Content-Disposition', 'attachment; filename='+filename);
res.send(pdfBuffer);
}
工作:
import {PDFDocument, rgb, StandardFonts } from 'pdf-lib';
export async function modifyPDF(firstname, lastname, id) {
const order_id = id;
const fullname = firstname + " " + lastname;
const existingPdfBytes = await fetch("https://pdf-lib.js.org/assets/us_constitution.pdf").then((res) => res.arrayBuffer());
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
const watermark = fullname + " (OrderID: " + id + ")";
// Set Document Metadata
pdfDoc.setSubject(watermark);
// Get pages
const pages = pdfDoc.getPages();
// Iterate every page, skip first
//pages.slice(1).forEach(page => {
pages.forEach(page => {
// Get the width and height of the page
const {
width,
height
} = page.getSize()
// Watermark the page
page.drawText(watermark, {
x: 70,
y: 8,
size: 10,
font: helveticaFont,
color: rgb(0.95, 0.1, 0.1),
})
})
const pdfBytes = await pdfDoc.save();
return Buffer.from(pdfBytes.buffer, 'binary');
}
export default async function handler(req, res) {
const filename = "test.pdf";
const {id, firstname, lastname} = req.query;
const pdfBuffer = await modifyPDF(firstname, lastname, id);
res.status(200);
res.setHeader('Content-Type', 'application/pdf'); // Displsay
res.setHeader('Content-Disposition', 'attachment; filename='+filename);
res.send(pdfBuffer);
}
【问题讨论】: