Skip to content

Commit

Permalink
Feat: add heif upload support (*.heic, e.g., for iOS devices) (#1375)
Browse files Browse the repository at this point in the history
* Add heif support through pillow-heif

* fix isort

* Mark no cover

* Pin Pillow to <10 for tests
  • Loading branch information
fsbraun authored Jul 5, 2023
1 parent 46e7e28 commit 6a8d981
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ CHANGELOG
* Add an edit button to the file widget which opens edit file pop-up
* Refactored directory list view for significant performance increases
* Remove thumbnail generation from the directory list view request response cycle
* Support for upload of webp images
* Optional support for upload of heif images
* Add Django 4.2 support
* Add thumbnail view for faster visual management of image libraries
* Fix File.objects.only() query required for deleting user who own files.
Expand Down
13 changes: 13 additions & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ The easiest way to get ``django-filer`` is simply install it with `pip`_::

$ pip install django-filer

Optional heic support
---------------------

Currently, django-filer supports upload of heif images (``*.heic``, such as
retrieved from iOS devices by airdrop) using an optional dependency::

$ pip install django-filer\[heif\]


Dependencies
------------
Expand All @@ -31,6 +39,11 @@ check `Pillow doc`_.
* for `Django`_ >=3.0 use `django-polymorphic`_ >=2.1
* for `Django`_ >=3.1 use `django-polymorphic`_ >=3.0

If heif support is chosen, django-filer also installs

* pillow-heif


Configuration
-------------

Expand Down
19 changes: 18 additions & 1 deletion filer/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@ class FilerConfig(AppConfig):
name = 'filer'
verbose_name = _("Filer")

def ready(self):
def register_optional_heif_supprt(self):
try: # pragma: no cover
from pillow_heif import register_heif_opener

from .settings import IMAGE_EXTENSIONS, IMAGE_MIME_TYPES

register_heif_opener()
IMAGE_EXTENSIONS += [".heic", ".heics", ".heif", ".heifs", ".hif"]
IMAGE_MIME_TYPES.append("heic")
except (ModuleNotFoundError, ImportError):
# No heif support installed
pass

def resolve_validators(self):
"""Resolve dotted path file validators"""

import importlib
Expand Down Expand Up @@ -37,3 +50,7 @@ def ready(self):
except (ImportError, ModuleNotFoundError, AttributeError):
raise ImproperlyConfigured(f"""filer: could not import validator "{item}".""")
self.FILE_VALIDATORS[mime_type] = functions

def ready(self):
self.resolve_validators()
self.register_optional_heif_supprt()
3 changes: 2 additions & 1 deletion filer/management/commands/import_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ def import_file(self, file_obj, folder):
"""
Create a File or an Image into the given folder
"""
from ...settings import IMAGE_EXTENSIONS
try:
iext = os.path.splitext(file_obj.name)[1].lower()
except: # noqa
iext = ''
if iext in ['.jpg', '.jpeg', '.png', '.gif', '.webp']:
if iext in IMAGE_EXTENSIONS:
obj, created = Image.objects.get_or_create(
original_filename=file_obj.name,
file=file_obj,
Expand Down
4 changes: 2 additions & 2 deletions filer/models/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ class Meta:
@classmethod
def matches_file_type(cls, iname, ifile, mime_type):
# source: https://www.freeformatter.com/mime-types-list.html
image_subtypes = ['gif', 'jpeg', 'png', 'x-png', 'svg+xml', 'webp']
from ..settings import IMAGE_MIME_TYPES
maintype, subtype = mime_type.split('/')
return maintype == 'image' and subtype in image_subtypes
return maintype == 'image' and subtype in IMAGE_MIME_TYPES

def file_data_changed(self, post_init=False):
attrs_updated = super().file_data_changed(post_init=post_init)
Expand Down
2 changes: 2 additions & 0 deletions filer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ def update_server_settings(settings, defaults, s, t):
}

DEFERRED_THUMBNAIL_SIZES = (40, 80, 160)
IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
IMAGE_MIME_TYPES = ['gif', 'jpeg', 'png', 'x-png', 'svg+xml', 'webp']

FILE_VALIDATORS = {
"text/html": ["filer.validation.deny_html"],
Expand Down
8 changes: 8 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
]


EXTRA_REQUIREMENTS = {
"heif": [
"pillow-heif",
],
}


CLASSIFIERS = [
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
Expand Down Expand Up @@ -61,6 +68,7 @@
include_package_data=True,
zip_safe=False,
install_requires=REQUIREMENTS,
extras_require=EXTRA_REQUIREMENTS,
python_requires='>=3.8',
classifiers=CLASSIFIERS,
test_suite='tests.settings.run',
Expand Down
2 changes: 1 addition & 1 deletion tests/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# requirements from setup.py
Pillow
Pillow<10 # Remove pinning for 3.0.0 release

# other requirements
coverage
Expand Down

0 comments on commit 6a8d981

Please sign in to comment.