Changing 'file properties' on download

I want to add some properties ‘on file download’. What is the ‘correct’ way of doing this. Basically, I want to add ‘properties’ to word, which I think I can do with ‘docx’.

Should I just override the ‘@@download’ view?

Basically I (just) want to do this (probably check for mimetype instead of 'filename

    if filename.lower().endswith(".docx"):
        try:
            doc = Document(BytesIO(file_data))
            props = doc.core_properties
            props.title = item.Title() or "File from XXXXX"
            props.author = "Somebody"
            props.subject = "Requested document"
            props.keywords = "Plone, etc"

            buffer = BytesIO()
            doc.save(buffer)
            file_data = buffer.getvalue()
        except Exception as e:
            pass

I would modify it when uploading, adding the properties. You can keep also the original version with CMFEditions, and serve the modified one. It depends on the use case, loading in memory and modifying a file at each download seems heavy to me. Pdfs has incremental updates that can help, you can stream the original file and then just add modifications at the end. I don’t know if docx has this feature.

Such changes should be made upon upload, never upon download.

I think my customer needs to set them based on user ( something to do with word macros, custom word toolbar)

Not word, I assume

You could override Download.__call__().

Get the original stream_data, add some properties, and return the propertied stream data.

from zope.publisher.interfaces import IPublishTraverse
from plone.namedfile.browser import Download
from zope.interface import implementer
from plone.namedfile.utils import stream_data
from plone.namedfile.utils import extract_media_type
from docx import Document
from io import BytesIO

@implementer(IPublishTraverse)
class DownloadWithProperties(Download):
    def __call__(self):
        file = self._getFile()
        self.set_headers(file)
        request_range = self.handle_request_range(file)
        mimetype = extract_media_type(file.contentType)
        if mimetype == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
            document = Document(BytesIO(file.data))
            document.core_properties.author = "Some Author"
            # ...
            buffer = BytesIO()
            document.save(buffer)
            return buffer.getvalue()
        return stream_data(file, **request_range)
  <browser:page
      name="download_with_properties"
      for="*"
      class=".DownloadWithProperties"
      permission="zope2.View"
      />