Next.js API:使用 URL 中的查询参数为 PDF 加水印

Next.js API: Watermark PDF using query parameters in URL

这是我第一次测试 Next.js API,我对整个 Next 也很陌生。js/React 世界请多多包涵。

此 API 路由的目标是触发自动下载带有自定义水印的 PDF,该自定义水印由 API URL 查询参数生成,如下所示:/api/PDFWatermark?id=123&firstname=John&lastname=Doe

为了创建水印,我使用 pdf-lib and I am using a modified version of this 代码为我的 PDF 添加水印。为了生成原始 PDF pdfDoc 的修改和可下载版本,我尝试使用 pdfBytes after 水印创建一个 blob。创建 blob 后,我想我可以将它添加到附加到 DOM.

的锚点

注释掉blobanchor代码时,出现两个错误:

  1. ReferenceError: Blob 未定义
  2. ReferenceError: document is not defined(可能是因为没有DOM附加锚点link)

此时我只能将 pdfBytes 打印为 json,我无法创建和下载实际的水印 PDF 文件。

有没有办法在调用 API 时自动将 pdfBytes 下载为 PDF 文件?

更新

modifyPDF 更改为 return 缓冲区后,下面的工作代码:

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);
}

将您的 modifyPDF 更改为 return 缓冲区

[...]
    const pdfBytes = await pdfDoc.save();
    return Buffer.from(pdfBytes.buffer, 'binary');
[...]

让APIreturnPDF通过处理程序到浏览器:

export default async function handler(req, res) {

    const {id, firstname, lastname} = req.query;
    const pdfBuffer = await modifyPDF(firstname, lastname, id);
    res.status(200); 
    
    res.setHeader('Content-Type', 'application/pdf'); 
    res.setHeader('Content-Disposition', 'attachment; filename='+filename); 
    // Edited as the linked example reports: 
    // res.type('pdf'); // and might not work
    res.send(pdfBuffer);
}

未经测试,但您应该明白要点。

Here's the full example from the library itself