如何在App Engine上使用xhtml2pdf生成带有自定义字体的PDF?

时间:2015-07-25 20:36:19

标签: python google-app-engine font-face temporary-files xhtml2pdf

xhtml2pdf可以在App Engine上生成简单的PDF。

但现在我需要在生成的PDF中添加自定义字体,而且我似乎找不到一个简单的解决方案来执行此操作。

我将此CSS添加到HTML以转换为PDF:

    @font-face {
       font-family: OpenSans;
       src: url("http://mydomain/fonts/Open-Sans-regular.ttf");
    }
    body {
        font-family: OpenSans;
    }

产生此错误:

  File "[..]/xhtml2pdf/util.py", line 613, in getNamedFile
self.tmp_file = tempfile.NamedTemporaryFile()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/dist/tempfile.py", line 61, in PlaceHolder
  raise NotImplementedError("Only tempfile.TemporaryFile is available for use")
  NotImplementedError: Only tempfile.TemporaryFile is available for use
GAE不支持

tempfile,因此我尝试通过在GCS中创建临时文件来替换tempfile.NamedTemporaryFile(),如下所示:

self.tmp_file = gcs.open('/gcs_bucket_temp/temp_file', 
                         'w',
                         retry_params=gcs.RetryParams(backoff_factor=1.1))

但是这会产生难以修复的重大更改:xhtml2pdf对ttfonts.py中的临时文件进行大量读取访问(例如ttfonts.py:321 unpack('>L',self._ttf_data[self._pos - 4:self._pos])[0]),这似乎难以迁移使用GCS文件。

有没有人能够使用自定义字体在App Engine上使用xhtml2pdf生成PDF?

1 个答案:

答案 0 :(得分:3)

以下是对xhtml2pdf库的更改,我必须在App Engine上进行自定义@ font-face支持。基本上使用GCS来存储临时文件而不是文件系统。

ttfonts.py:239中,替换:

self.filename, f = TTFOpenFile(f)
self._ttf_data = f.read()

由:

self.filename = f
gcs_file = gcs.open(f) #, 'w', retry_params=gcs.RetryParams(backoff_factor=1.1))
self._ttf_data = gcs_file.read()
gcs_file.close()

util.py:608中,替换:

self.tmp_file = tempfile.NamedTemporaryFile()
if self.file:
    shutil.copyfileobj(self.file, self.tmp_file)
else:
    self.tmp_file.write(self.getData())
    self.tmp_file.flush()
return self.tmp_file

由:

filename = '/%s/temp_file'%gcs_bucket
self.tmp_file = gcs.open(filename, 'w', retry_params=gcs.RetryParams(backoff_factor=1.1))
if self.file:
    self.tmp_file.write(self.file._fetch_response.content)
else:
    self.tmp_file.write(self.getData())
self.tmp_file.close()
return filename

这似乎可以解决问题。自定义字体现在可以很好地显示在生成的PDF中。