From a32fb6a208f653a64487a6b0de481f90af659556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Tue, 8 Jan 2019 15:07:47 +0100 Subject: [PATCH] Storage: added function for setting content type, encoding, and attachmentness These are used by Flamenco to store task logs as gzipped text files, but to send them to the browser with such HTTP headers that the browser can gunzip them and display directly (rather than having to download & gunzip yourself). --- pillar/api/file_storage_backends/abstract.py | 9 ++++++++- pillar/api/file_storage_backends/gcs.py | 14 ++++++++++++-- pillar/api/file_storage_backends/local.py | 5 ++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pillar/api/file_storage_backends/abstract.py b/pillar/api/file_storage_backends/abstract.py index 3d02dc34..60501a24 100644 --- a/pillar/api/file_storage_backends/abstract.py +++ b/pillar/api/file_storage_backends/abstract.py @@ -132,12 +132,19 @@ class Blob(metaclass=abc.ABCMeta): file_size=file_size) @abc.abstractmethod - def update_filename(self, filename: str): + def update_filename(self, filename: str, *, is_attachment=True): """Sets the filename which is used when downloading the file. Not all storage backends support this, and will use the on-disk filename instead. """ + @abc.abstractmethod + def update_content_type(self, content_type: str, content_encoding: str = ''): + """Set the content type (and optionally content encoding). + + Not all storage backends support this. + """ + @abc.abstractmethod def get_url(self, *, is_public: bool) -> str: """Returns the URL to access this blob. diff --git a/pillar/api/file_storage_backends/gcs.py b/pillar/api/file_storage_backends/gcs.py index 7ecda06e..997d4487 100644 --- a/pillar/api/file_storage_backends/gcs.py +++ b/pillar/api/file_storage_backends/gcs.py @@ -174,7 +174,7 @@ class GoogleCloudStorageBlob(Blob): self.gblob.reload() self._size_in_bytes = self.gblob.size - def update_filename(self, filename: str): + def update_filename(self, filename: str, *, is_attachment=True): """Set the ContentDisposition metadata so that when a file is downloaded it has a human-readable name. """ @@ -182,7 +182,17 @@ class GoogleCloudStorageBlob(Blob): if '"' in filename: raise ValueError(f'Filename is not allowed to have double quote in it: {filename!r}') - self.gblob.content_disposition = f'attachment; filename="{filename}"' + if is_attachment: + self.gblob.content_disposition = f'attachment; filename="{filename}"' + else: + self.gblob.content_disposition = f'filename="{filename}"' + self.gblob.patch() + + def update_content_type(self, content_type: str, content_encoding: str = ''): + """Set the content type (and optionally content encoding).""" + + self.gblob.content_type = content_type + self.gblob.content_encoding = content_encoding self.gblob.patch() def get_url(self, *, is_public: bool) -> str: diff --git a/pillar/api/file_storage_backends/local.py b/pillar/api/file_storage_backends/local.py index 70d578a8..9bc1c1ee 100644 --- a/pillar/api/file_storage_backends/local.py +++ b/pillar/api/file_storage_backends/local.py @@ -113,10 +113,13 @@ class LocalBlob(Blob): self._size_in_bytes = file_size - def update_filename(self, filename: str): + def update_filename(self, filename: str, *, is_attachment=True): # TODO: implement this for local storage. self._log.info('update_filename(%r) not supported', filename) + def update_content_type(self, content_type: str, content_encoding: str = ''): + self._log.info('update_content_type(%r, %r) not supported', content_type, content_encoding) + def make_public(self): # No-op on this storage backend. pass