在 PDF 中嵌入 SVG(使用 JS 将 SVG 导出为 PDF)

Posted

技术标签:

【中文标题】在 PDF 中嵌入 SVG(使用 JS 将 SVG 导出为 PDF)【英文标题】:Embedding SVG in PDF (exporting SVG to PDF using JS) 【发布时间】:2011-08-20 06:40:32 【问题描述】:

起点:除了静态文件,我没有可以提供任何东西的服务器。我的<body> 中有一个 SVG 元素(动态创建),我想导出为矢量格式,最好是 PDF 或 SVG。

我开始考虑使用现有的库 jsPDF 和 downloadify。它工作得很好。不幸的是,这不支持 SVG,只支持文本。

我已经了解了 PDF 格式嵌入 SVG 图像的可能性,并且 it seems 自 Acrobat Reader 5(以及 ImageViewer 插件)以来已启用。但它不起作用。我尝试了 3 种不同的 PDF 阅读器,但均未成功。

这是否意味着 PDF 不再支持 SVG 嵌入?我在这方面没有找到任何东西。

我有两个问题;这可以解决吗?如果是,在 PDF 中嵌入 SVG 的规范是什么?有了这些信息,我可以自己在 jsPDF 中构建支持。

浏览器支持需求是 Safari、Chrome 和 Firefox。支持 SVG 的版本。

【问题讨论】:

【参考方案1】:

对于寻找纯 JS 解决方案的任何人:PDFKit 似乎是当今从 JS 生成 PDF 的最佳解决方案,它支持所有 SVG 几何原语(包括解释 path几何字符串)开箱即用。如果您不需要符号等复杂的东西,渲染现有 SVG 内容所需要的只是一个跟踪 CSS 样式和继承的 DOM-walker。

我在另一个答案中提到的 jsPDF/svgToPdf 组合的粗略 SVG 支持没有成功,而且这两个的源代码看起来不制作精良,对我来说很完整。

编辑:用法示例JSFiddle

【讨论】:

一个问题。 1.打开pdfkit.org/demo/browser.html。 2. 打开 Chrome 检查窗口。 3. 单击顶部菜单上的“切换设备工具栏”图标。 4. 刷新页面。 5. 我在移动视图的右侧窗口中看不到 pdf。 6. 有谁知道为什么移动视图不呈现 PDF。 ?在移动设备上打开 pdf 是 PDFKit 特有的还是一般的问题? PDFKit 与 github.com/alafr/SVG-to-PDFKit 结合似乎是要走的路。 不能直接将html转成pdf 不支持图片标签!?【参考方案2】:

我会回答我自己的问题。我最终使用了DocRaptor,它可以从 javascript 调用客户端。这在技术上解决了我的问题,即使它是一个非免费的解决方案。如果我的答案可能是服务器端解决方案,我可以将 wkhtmltopdf 用作麦克风的 proposed。

【讨论】:

感谢您提供指向 DocRaptor 的链接。如果你想托管一些东西,你可以使用 WKHTMLTOPDF,因为它是免费且开源的 添加了您的答案并删除了 Prince XML 作为替代方案,谢谢!【参考方案3】:

jsPDF 有一个插件:svgToPdf

https://github.com/ahwolf/jsPDF/blob/master/jspdf.plugin.svgToPdf.js

我没有尝试过,但这可能允许放弃使用外部 API 和/或不得不依赖服务器端解决方案。

【讨论】:

我目前正在尝试这种方法,但我似乎只能从中得到一个空白的 pdf。您知道使用此插件的任何示例吗?【参考方案4】:

您尝试过 WKHTMLTOPDF 吗?它是一个基于 webkit 的免费工具。 我们写了一个小教程here.

在 Mac 上,使用 Safari 或 Chrome,您可以将嵌入了 SVG 的 HTML 页面保存为 PDF。由于这些浏览器在内部使用 WKHTMLTOPDF,可能这也适合您。

【讨论】:

我在这里寻求客户端解决方案。但是,您是对的,因为我没有指定我要支持的浏览器。所以我现在编辑了我的答案以包含它 很遗憾,我仍然无法使 wkhtmltopdf 工作。它只会为我生成空白页。 @art-solopov,时代变了,如上所述,你可以切换到pdfkit:pdfkit.org/docs/vector.html【参考方案5】:

使用pdfkitsvg-to-pdfkitblob-stream 的最小示例,将 SVG DOM 元素下载为 PDF。

    在您的index.html 中导入包。
<script src="https://cdn.jsdelivr.net/npm/pdfkit@0.10.0/js/pdfkit.standalone.js"></script>
<script src="https://bundle.run/blob-stream@0.1.3"></script>
<script src="https://cdn.jsdelivr.net/npm/svg-to-pdfkit@0.1.8/source.js"></script>
    运行此函数,其中 svg 是 SVG DOM 元素或 SVG 字符串。
function downloadPDF(svg, outFileName) 
    let doc = new PDFDocument(compress: false);
    SVGtoPDF(doc, svg, 0, 0);
    let stream = doc.pipe(blobStream());
    stream.on('finish', () => 
      let blob = stream.toBlob('application/pdf');
      const link = document.createElement('a');
      link.href = URL.createObjectURL(blob);
      link.download = outFileName + ".pdf";
      link.click();
    );
    doc.end();

【讨论】:

【参考方案6】:

EVO HTML to PDF Converter 支持将嵌入在 HTML 中的 SVG 转换为 PDF。您可以在此处查看此功能的示例:http://www.evopdf.com/demo/HTML_to_PDF/HTML5_Features/SVG_to_PDF.aspx。示例代码是:

// Create a HTML to PDF converter object with default settings
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();

// Convert the HTML page with SVG to a PDF document in a memory buffer
byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(urlHtmlWithSVG);

// Send the PDF as response to browser

// Set response content type
Response.AddHeader("Content-Type", "application/pdf");

// Instruct the browser to open the PDF file as an attachment or inline
Response.AddHeader("Content-Disposition", String.Format("attachment; filename=SVG_to_PDF.pdf; size=0", outPdfBuffer.Length.ToString()));

// Write the PDF document buffer to HTTP response
Response.BinaryWrite(outPdfBuffer);

// End the HTTP response and stop the current page processing
Response.End();

【讨论】:

EVO pdf 不适合整个 pdf 页面上的 svg 图像。图像的所有侧面都有很多空白区域。我尝试了所有选项,如 FitWidth、FitHeight、StretchToFit 等。但无法解决问题。 我遇到了与 ArpitGupta 相同的问题,使用 @EvoPdf 时 SVG 周围的布局完全错误 我有一个包装 SVG 的容器 div,我正在使用 flexbox 将容器。转换为 PDF 时,布局/对齐方式与我完全删除 flexbox 样式相同。

以上是关于在 PDF 中嵌入 SVG(使用 JS 将 SVG 导出为 PDF)的主要内容,如果未能解决你的问题,请参考以下文章

嵌入 SVG 时 wkhtmltopdf 失败

python导入svg图片格式

使用 iText 将 SVG 转换为 PDF,SVG 未在 PDF 中完全显示

SVG 嵌入图像仅在浏览器中显示

有没有办法像真正的 html 元素而不是画布或 svg 一样呈现 pdf.js 页面?

在 SVG 元素中嵌入快速动画/SWF