Which works as intended as long as the name of my scale does not contain an underscore or hyphen. Unfortunately I am too far in the project to consider renaming my scales.
When the scalename does include an underscore or hyphen, I get the following traceback:
EDIT
Which works as intended as long as the scale has not been cropped.
2021-09-22 14:30:51,052 ERROR [plone.namedfile.scaling:259][waitress] Could not scale "<plone.namedfile.file.NamedImage object at 0x7f21dce065f0 oid 0x228db in <Connection at 7f21f2c7b910>>" of 'http://localhost:8888/PNZ/de/assets-de/downloads/nachhaltigkeit/verhaltenskodex-fuer-unsere-partner'
Traceback (most recent call last):
File "/usr/local/Plone52/buildout-cache/eggs/plone.namedfile-5.5.1-py3.9.egg/plone/namedfile/scaling.py", line 249, in __call__
result = self.create_scale(
File "/usr/local/Plone52/buildout-cache/eggs/plone.app.imagecropping-2.2.2-py3.9.egg/plone/app/imagecropping/dx.py", line 42, in create_scale
data = self._crop(data, self.box)
File "/usr/local/Plone52/buildout-cache/eggs/plone.app.imagecropping-2.2.2-py3.9.egg/plone/app/imagecropping/dx.py", line 31, in _crop
image = PIL.Image.open(data)
File "/usr/local/Plone52/buildout-cache/eggs/Pillow-6.2.2-py3.9-linux-x86_64.egg/PIL/Image.py", line 2766, in open
fp = builtins.open(filename, "rb")
ValueError: embedded null byte
2021-09-22 14:30:51,735 ERROR [Zope.SiteErrorLog:252][waitress] 1632313851.73454330.5442225585189057 http://localhost:8888/PNZ/de/assets-de/downloads/nachhaltigkeit/verhaltenskodex-fuer-unsere-partner/@@images/image
Traceback (innermost last):
Module ZPublisher.WSGIPublisher, line 162, in transaction_pubevents
Module ZPublisher.WSGIPublisher, line 371, in publish_module
Module ZPublisher.WSGIPublisher, line 250, in publish
Module ZPublisher.BaseRequest, line 532, in traverse
Module ZPublisher.HTTPResponse, line 1022, in debugError
zExceptions.NotFound: Cannot locate object at: http://localhost:8888/PNZ/de/assets-de/downloads/nachhaltigkeit/verhaltenskodex-fuer-unsere-partner/@@images/image
I fail to understand why this could happen. Any insights?
class PDFImagePreview(BrowserView):
""" update a PDF object with a preview image
protected by zcml permission cmf.ModifyPortalContent
"""
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
context = self.context
request = self.request
data = get_pdf_preview(context)
filename = u'pdf_preview'
filename_extension = u'.pdf'
pdf_filename = context.getId().lower()
if pdf_filename.endswith(filename_extension):
filename = pdf_filename.split(filename_extension)[0]
#log.info('creating pdf preview with filename: %s' % filename)
context.image = NamedImage(
data = data,
contentType = 'image/jpeg',
filename = u'%s.jpg' % filename)
def get_pdf_preview(context=None, single_file=True):
""" https://github.com/Belval/pdf2image
images = convert_from_bytes(pdf_file, dpi=200, output_folder=None
, first_page=None, last_page=None, fmt='ppm'
, thread_count=1, userpw=None, use_cropbox=False
, strict=False, transparent=False
, single_file=False, output_file=str(uuid.uuid4())
, poppler_path=None, grayscale=False)
images will be a list of PIL Image representing each page of the PDF document.
"""
image_file = io.BytesIO()
data = context.file.data
image = convert_from_bytes( data, fmt='jpg', dpi=150
, single_file=single_file)[0]
image.save(image_file, format='jpeg')
image_data = image_file.getvalue()
return image_data
It does not matter if I write my image as BytesIO(image_data) - but it does matter if the image passed to PIL is a BytesIO object. Forcing this, fixes the issue:
from ZODB.blob import BlobFile
def _crop(self, data, box, default_format='PNG'):
"""crop data (image as open file) to box
"""
# Force NamedImage data to be a BytesIO object
if not isinstance(data, BlobFile):
data = BytesIO(data)