简体   繁体   English

从 SVG 输入生成 PDF

[英]Generating PDFs from SVG input

I am trying to generate a PDF from a SVG input file with Python in a Django application.我正在尝试从 SVG 输入文件中生成 PDF 和 Python 应用程序。

I have already found 2 working solutions: cairo+rsvg and imagemagick but they both have one problem: They have some strange dependencies that I do not want to install on a server, for example DBUS and GTK.我已经找到了 2 个可行的解决方案:cairo+rsvg 和 imagemagick,但它们都有一个问题:它们有一些我不想在服务器上安装的奇怪依赖项,例如 DBUS 和 GTK。

So I am asking for another method for generating a PDF from SVG without having to install all these stupid dependencies on a server.所以我要求另一种方法从 SVG 生成 PDF 而不必在服务器上安装所有这些愚蠢的依赖项。

Have you considered svglib ?你考虑过 svglib吗?

It looks quite promising, especially as reportlab is the featured pdf tool in Django's docs.它看起来很有希望,特别是因为 reportlab 是 Django 文档中的特色 pdf 工具

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF

drawing = svg2rlg("file.svg")
renderPDF.drawToFile(drawing, "file.pdf")

Yes, I would also suggest using svglib and the reportlab library for this task although there is very little documentation of the svglib library.是的,我还建议使用svglibreportlab 库来完成这项任务,尽管 svglib 库的文档很少。 I would actually suggest doing the following in your Django view:我实际上建议在您的 Django 视图中执行以下操作:

from svglib.svglib import SvgRenderer
from reportlab.graphics import renderPDF
import xml.dom.minidom
@csrf_exempt
def export_svg(request):
    # Get data from client side via POST variables
    svg = request.POST.get("svg")
    doc = xml.dom.minidom.parseString(svg.encode( "utf-8" ))
    svg = doc.documentElement
    # Create new instance of SvgRenderer class
    svgRenderer = SvgRenderer()
    svgRenderer.render(svg)
    drawing = svgRenderer.finish()

    # Instead of outputting to a file, we simple return
    # the data and let the user download to their machine
    pdf = renderPDF.drawToString(drawing)
    response = HttpResponse(mimetype='application/pdf')
    response.write(pdf)     

    # If one were to remove the 'attachment; ' from this line
    # it would simple invoke the browsers default PDF plugin
    response["Content-Disposition"]= "attachment; filename=converted.pdf"
    return response

This way you never need to save a temporary file on the server for the user to just download locally anyway.这样,您永远不需要在服务器上保存临时文件,以便用户无论如何都可以在本地下载。 The svglib example that is given requires providing a path to a file... but why not just provide the file itself?给出的 svglib 示例需要提供文件的路径......但为什么不只提供文件本身呢?

I have documented the steps I have taken using Django and the Raphael SVG library here .我在这里记录了我使用 Django 和 Raphael SVG 库所采取的步骤。

My answer may help someone on macOS:我的回答可能会对 macOS 上的人有所帮助:

I user CairoSVG我用户CairoSVG

Firstly, install it with:首先,安装它:

pip install cairosvg

Then you can use it in Python:然后就可以在Python中使用了:

>>> import cairosvg
>>> cairosvg.svg2pdf(url='image.svg', write_to='image.pdf')

from its documentation :从其文档中:

on macOS, you'll have to install cairo and libffi (with Homebrew for example)在 macOS 上,您必须安装cairolibffi (例如使用 Homebrew)

You will need to add "import string" for version 0.6.3 to work with python 2.7.您需要为版本 0.6.3 添加“导入字符串”才能与 python 2.7 一起使用。

you can use my frok until the pypy is updated.在更新 pypy 之前,您可以使用我的 frok。

pip install git+git://github.com/ddehghan/libsvg.git

As these answers are all quite old, I would like to post a modern solution using CairoSVG由于这些答案都很老了,我想发布一个使用CairoSVG的现代解决方案

This works with Django views:这适用于 Django 视图:

import cairosvg

def export_svg(request):
    # Get data from POST
    svg = request.POST.get("svg")
    pdf = cairosvg.svg2pdf(bytestring=svg.encode("utf-8"))

    # The pdf is now a bytestring that can be returned instead of saving to disk. 
    response = HttpResponse(mimetype='application/pdf')
    response.write(pdf)     

I personally use pdfkit wrapper for Wkhtmltopdf .我个人将pdfkit包装器用于Wkhtmltopdf I tested with your example of SVG and it does have opacity.我用您的 SVG 示例进行了测试,它确实具有不透明度。

Though, to test - I've enclosed SVG file into HTML and then converted HTML to PDF.虽然,为了测试 - 我已经将 SVG 文件附在 HTML 中,然后将 HTML 转换为 ZBCD1B6861776B51DFCZFF04038

You can give it a try on my server (which uses Wkhtmltopdf ):您可以在我的服务器(使用Wkhtmltopdf )上试一试:

response = requests.post('http://194.67.110.124:8000/html_to_pdf/',
                         files={
                             'template': ('template.html', open('template.html', 'rb')),
                             'picture': ('template.svg', open('template.svg', 'rb'))
                         },
                         data={})

where template.html is an HTML file contained SVG with prefix {{image_path}} .其中template.html是一个 HTML 文件,其中包含前缀为{{image_path}}的 SVG 。 For example:例如:

<!DOCTYPE html>
<html lang="en">
<img src="{{image_path}}/template.svg">
</html>

and template.svg if the SVG file.template.svg如果 SVG 文件。 The result I get is:我得到的结果是:

在此处输入图像描述

The code for pdfkit is quite simple: pdfkit 的代码非常简单:

import pdfkit

pdfkit.from_file('template.html', 'output.pdf')

Where template.html contains the embedded SVG.其中template.html包含嵌入式 SVG。

Note that pdfkit is only a wrapper and Wkhtmltopdf app has to be installed on the machine.请注意, pdfkit只是一个包装器,必须在机器上安装Wkhtmltopdf应用程序。 (BTW, on Windows it's quite slow) (顺便说一句,在 Windows 上它很慢)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM