Как создать PDF-файл с пользовательским шрифтом с помощью xhtml2pdf в App Engine?

xhtml2pdf отлично подходит для создания простого PDF-файла в App Engine.

Но теперь мне нужно добавить собственный шрифт в сгенерированный 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

tempfile не поддерживается GAE, поэтому я попытался заменить tempfile.NamedTemporaryFile(), создав временный файл в GCS следующим образом:

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.

Кто-нибудь смог создать PDF-файлы с помощью xhtml2pdf в App Engine с пользовательскими шрифтами?


person user2779653    schedule 25.07.2015    source источник


Ответы (1)


Вот изменения в библиотеке xhtml2pdf, которые мне пришлось внести, чтобы включить поддержку пользовательского @font-face в App Engine. В основном используется GCS для хранения временного файла вместо файловой системы.

В ttfonts.py:239 заменить:

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

by:

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

by:

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-файлах.

person user2779653    schedule 26.07.2015