diff --git a/CHANGES.rst b/CHANGES.rst index b58c8136..b5b69af6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Changelog 1.11 (unreleased) ----------------- +- Try to restore broken blobs when exporting content. + [thet] + - When exporting into separate JSON files write also the error in a separate errors.json file. This fixes an error at the end of the export and no errors being written. [thet] diff --git a/src/collective/exportimport/serializer.py b/src/collective/exportimport/serializer.py index d7695a76..2eed52f2 100644 --- a/src/collective/exportimport/serializer.py +++ b/src/collective/exportimport/serializer.py @@ -75,29 +75,6 @@ def get_blob_path(blob): # Custom Serializers for Dexterity -@adapter(INamedImageField, IDexterityContent, IBase64BlobsMarker) -class ImageFieldSerializerWithBlobs(DefaultFieldSerializer): - def __call__(self): - try: - image = self.field.get(self.context) - except AttributeError: - image = None - if not image: - return None - - if "built-in function id" in image.filename: - filename = self.context.id - else: - filename = image.filename - - result = { - "filename": filename, - "content-type": image.contentType, - "data": base64.b64encode(image.data), - "encoding": "base64", - } - return json_compatible(result) - @adapter(INamedFileField, IDexterityContent, IBase64BlobsMarker) class FileFieldSerializerWithBlobs(DefaultFieldSerializer): @@ -109,10 +86,27 @@ def __call__(self): if namedfile is None: return None - if "built-in function id" in namedfile.filename: - filename = self.context.id - else: - filename = namedfile.filename + try: + if "built-in function id" in namedfile.filename: + filename = self.context.id + else: + filename = namedfile.filename + except AttributeError: + # Try to recover broken namedfile + # Related to: WARNING OFS.Uninstalled Could not import class 'NamedBlobFile' from module 'zope.app.file.file' + from ZODB.broken import Broken + + if isinstance(namedfile, Broken): + broken_namedfile = namedfile.__Broken_state__ + file = broken_namedfile["_blob"].open() + result = { + "filename": broken_namedfile["filename"], + "content-type": broken_namedfile["contentType"], + "data": base64.b64encode(file.read()), + "encoding": "base64", + } + file.close() + return result result = { "filename": filename, @@ -123,6 +117,11 @@ def __call__(self): return json_compatible(result) +@adapter(INamedImageField, IDexterityContent, IBase64BlobsMarker) +class ImageFieldSerializerWithBlobs(FileFieldSerializerWithBlobs): + pass + + @adapter(IRichText, IDexterityContent, IRawRichTextMarker) class RichttextFieldSerializerWithRawText(DefaultFieldSerializer): def __call__(self):