Fix exception of Pillow for SVGs
Review Request #10851 — Created Jan. 24, 2020 and submitted — Latest diff uploaded
If someone uploads a SVG as file attachment Review Boards tries to generate a thumbnail. Pillow do not support SVGs and throws an exception. https://github.com/python-pillow/Pillow/issues/3509 - djblets.util.templatetags.djblets_images - Error thumbnailing image file uploaded/files/2020/01/24/d6a12e49-05b7-42d9-bd6c-50985fd98f8e__check.svg and saving as uploaded/files/2020/01/24/d6a12e49-05b7-42d9-bd6c-50985fd98f8e__check_600.svg: cannot identify image file <cStringIO.StringI object at 0x7ff6a9b57b58> Traceback (most recent call last): File "/opt/reviewboard/dist/lib/python2.7/site-packages/djblets/util/templatetags/djblets_images.py", line 126, in thumbnail image = Image.open(data) File "/opt/reviewboard/dist/lib/python2.7/site-packages/PIL/Image.py", line 2705, in open % (filename if filename else fp)) IOError: cannot identify image file <cStringIO.StringI object at 0x7ff6a9b57b58> As SVG do not need thumbnail because Browsers can scale that without a problem we can provide the original file here.
Added an SVG file and saw that the thumbnail exists
instead of an error 404.
djblets/util/templatetags/djblets_images.py | |||
---|---|---|---|
Revision 53e954809457dd8acf459e59982c6297a2e6ca19 | New Change | ||
23 lines | |||
24 |
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24 |
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25 | 25 | ||
26 |
from __future__ import division, unicode_literals |
26 |
from __future__ import division, unicode_literals |
27 | 27 | ||
28 |
import logging |
28 |
import logging |
29 |
import os |
||
29 |
import re |
30 |
import re |
30 | 31 | ||
31 |
from django import template |
32 |
from django import template |
32 |
from django.template import TemplateSyntaxError |
33 |
from django.template import TemplateSyntaxError |
33 |
from django.utils import six |
34 |
from django.utils import six |
34 |
from django.utils.html import format_html, format_html_join |
35 |
from django.utils.html import format_html, format_html_join |
35 |
from django.utils.six.moves import cStringIO as StringIO |
36 |
from django.utils.six.moves import cStringIO as StringIO |
36 |
from django.utils.translation import ugettext as _ |
37 |
from django.utils.translation import ugettext as _ |
37 |
from PIL import Image |
38 |
from PIL import Image |
39 |
from PIL.Image import registered_extensions |
||
38 | 40 | ||
39 |
from djblets.util.decorators import blocktag |
41 |
from djblets.util.decorators import blocktag |
40 | 42 | ||
41 | 43 | ||
42 |
logger = logging.getLogger(__name__) |
44 |
logger = logging.getLogger(__name__) |
47 lines | |||
def thumbnail(f, size='400x100'):
|
|||
90 |
This will create a thumbnail of the given ``file`` (a Django FileField or
|
92 |
This will create a thumbnail of the given ``file`` (a Django FileField or
|
91 |
ImageField) with the given size. Size can either be a string of WxH (in
|
93 |
ImageField) with the given size. Size can either be a string of WxH (in
|
92 |
pixels), or a 2-tuple. If the size is a tuple and the second part is None,
|
94 |
pixels), or a 2-tuple. If the size is a tuple and the second part is None,
|
93 |
it will be calculated to preserve the aspect ratio.
|
95 |
it will be calculated to preserve the aspect ratio.
|
94 | 96 | ||
97 |
If the image format is not registered in PIL the thumbnail is not generated
|
||
98 |
and returned as-is.
|
||
99 | |||
95 |
This will return the URL to the stored thumbnail.
|
100 |
This will return the URL to the stored thumbnail.
|
96 |
"""
|
101 |
"""
|
102 |
storage = f.storage |
||
103 |
ext = os.path.splitext(f.name)[1].lower() |
||
104 |
if ext not in registered_extensions(): |
||
105 |
return storage.url(f.name) |
||
106 | |||
97 |
if isinstance(size, six.string_types): |
107 |
if isinstance(size, six.string_types): |
98 |
x, y = (int(x) for x in size.split('x')) |
108 |
x, y = (int(x) for x in size.split('x')) |
99 |
size_str = size |
109 |
size_str = size |
100 |
elif isinstance(size, tuple): |
110 |
elif isinstance(size, tuple): |
101 |
x, y = size |
111 |
x, y = size |
11 lines | |||
def thumbnail(f, size='400x100'):
|
|||
113 |
miniature = '%s_%s.%s' % (basename, size_str, format) |
123 |
miniature = '%s_%s.%s' % (basename, size_str, format) |
114 |
else: |
124 |
else: |
115 |
basename = filename |
125 |
basename = filename |
116 |
miniature = '%s_%s' % (basename, size_str) |
126 |
miniature = '%s_%s' % (basename, size_str) |
117 | 127 | ||
118 |
storage = f.storage |
||
119 | |||
120 |
if not storage.exists(miniature): |
128 |
if not storage.exists(miniature): |
121 |
try: |
129 |
try: |
122 |
f = storage.open(filename, 'rb') |
130 |
f = storage.open(filename, 'rb') |
123 |
data = StringIO(f.read()) |
131 |
data = StringIO(f.read()) |
124 |
f.close() |
132 |
f.close() |
160 lines |