xhtml2pdf 与位于 windows 项目根目录的图像配合使用效果很好,但在部署到 Ubuntu 时会中断

xhtml2pdf works great with an Image located at project's root on windows but breaks when deployed to Ubuntu

我有一个非常奇怪的问题,我尝试了大约 5 个小时的所有方法来解决这个奇怪的问题,但没有成功。

我能够在 运行 windows 10 的机器上使用 xhtml2pdf 成功生成带有图像的 PDF 文件,但是当我部署到 Ubuntu 我的图片无缘无故坏了!

我认为问题在于,在 Ubuntu 上,它没有正确构建此图像的路径,但具有讽刺意味的是,它在 windows 上却完美无缺!

这是在 windows 上运行良好但在 Ubuntu 上运行良好的部分:

<table>
        <tr>
            <td> <img src="test_logo.png" alt="logo"></td>
        </tr>
</table>

并且 test_logo.png 位于我项目的根目录,就像这样:

my_project/
   app1/
   app2/
   requirements.txt
   test_logo.png

还有我的link_callback()

def link_callback(uri, rel):
    """
    Convert HTML URIs to absolute system paths so xhtml2pdf can access those
    resources
    """

    sUrl = settings.STATIC_URL        # Typically /static/
    sRoot = settings.STATIC_ROOT      # Typically /home/userX/project_static/
    mUrl = settings.MEDIA_URL         # Typically /media/
    mRoot = settings.MEDIA_ROOT       # Typically /home/userX/project_static/media/

    if uri.startswith(mUrl):
        path = os.path.join(mRoot, uri.replace(mUrl, ""))
    elif uri.startswith(sUrl):
        path = os.path.join(sRoot, uri.replace(sUrl, ""))
    else:
        return uri

    # make sure that file exists
    if not os.path.isfile(path):
        raise Exception(
            'media URI must start with %s or %s' % (sUrl, mUrl)
        )
    return path

我正在使用 Django 2.2.18python 3.8

的最新 xhtml2pdf 版本

这很奇怪,它应该适用于所有平台或根本不适用。

谢谢

终于找到问题了!

在查看了 xhtml2pdf 如何获取文件 here 之后,事实证明,对于没有路径的文件,它获取当前工作目录并使用它,这对我有用 windows 因为我的环境位于项目的根目录,所以文件在那里,但在 ubuntu 处损坏,因为我的环境与项目所在的位置完全不同。

知道这个之后,修复就很简单了,就是 return BASE_DIR 路径,这是我修复后的 lick_callback()

def link_callback(uri, rel):
    """
    Convert HTML URIs to absolute system paths so xhtml2pdf can access those
    resources
    """

    sUrl = settings.STATIC_URL            # Typically /static/
    sRoot = settings.STATIC_ROOT          # Typically /home/userX/project_static/
    mUrl = settings.MEDIA_URL             # Typically /media/
    mRoot = settings.MEDIA_ROOT           # Typically /home/userX/project_static/media/
    bRoot = settings.BASE_DIR             # Project's base directory

    if uri.startswith(mUrl):
        path = os.path.join(mRoot, uri.replace(mUrl, ""))
    elif uri.startswith(sUrl):
        path = os.path.join(sRoot, uri.replace(sUrl, ""))
    else:
        return os.path.join(bRoot, '../', uri)

    # make sure that file exists
    if not os.path.isfile(path):
        raise Exception(
            'media URI must start with %s or %s' % (sUrl, mUrl)
        )
    return path