0001-misc-add-support-for-thumbnailing-PDF-files-26632.patch
debian/control | ||
---|---|---|
25 | 25 |
python-qrcode, |
26 | 26 |
libjs-leaflet, |
27 | 27 |
python-magic, |
28 |
python-docutils |
|
28 |
python-docutils, |
|
29 |
graphicsmagick |
|
29 | 30 |
Suggests: python-libxml2, |
30 | 31 |
python-lasso, |
31 | 32 |
python-psycopg2 |
wcs/fields.py | ||
---|---|---|
33 | 33 |
from qommon import _ |
34 | 34 |
from qommon import evalutils |
35 | 35 |
from qommon.form import * |
36 |
from qommon.misc import localstrftime, strftime, date_format, ellipsize |
|
36 |
from qommon.misc import localstrftime, strftime, date_format, ellipsize, can_thumbnail
|
|
37 | 37 |
from qommon.template import Template, TemplateError |
38 | 38 |
from qommon import get_cfg, get_logger |
39 | 39 | |
... | ... | |
907 | 907 |
t = TemplateIO(html=True) |
908 | 908 |
t += htmltext('<div class="file-field">') |
909 | 909 |
t += htmltext('<a download="%s" href="[download]?f=%s">') % (value.base_filename, self.id) |
910 |
if value.content_type and value.content_type.startswith('image/'):
|
|
910 |
if can_thumbnail(value.content_type):
|
|
911 | 911 |
t += htmltext('<img alt="" src="[download]?f=%s&thumbnail=1"/>') % self.id |
912 | 912 |
t += htmltext('<span>%s</span>') % value |
913 | 913 |
t += htmltext('</a></div>') |
wcs/forms/common.py | ||
---|---|---|
81 | 81 |
response.set_header( |
82 | 82 |
'content-disposition', 'attachment; filename="%s"' % file.base_filename) |
83 | 83 | |
84 |
fp = file.get_file_pointer() |
|
85 |
if self.thumbnails and file.content_type.startswith('image/'): |
|
84 |
if self.thumbnails and misc.can_thumbnail(file.content_type): |
|
86 | 85 |
try: |
87 |
thumbnail = misc.get_thumbnail(fp) |
|
88 |
except misc.ThumbnailError: |
|
89 |
pass |
|
90 |
else: |
|
86 |
thumbnail = misc.get_thumbnail(file.get_filename(), |
|
87 |
content_type=file.content_type) |
|
91 | 88 |
response.set_content_type('image/png') |
92 | 89 |
return thumbnail |
90 |
except misc.ThumbnailError: |
|
91 |
pass |
|
93 | 92 | |
94 |
return fp.read()
|
|
93 |
return file.get_file_pointer().read()
|
|
95 | 94 | |
96 | 95 | |
97 | 96 |
class FilesDirectory(Directory): |
wcs/forms/root.py | ||
---|---|---|
1114 | 1114 |
if tempfile['charset']: |
1115 | 1115 |
response.set_charset(tempfile['charset']) |
1116 | 1116 | |
1117 |
file_pointer = get_session().get_tempfile_content(t).get_file_pointer() |
|
1118 | 1117 |
if get_request().form.get('thumbnail') == '1': |
1119 | 1118 |
try: |
1120 |
thumbnail = misc.get_thumbnail(file_pointer) |
|
1119 |
thumbnail = misc.get_thumbnail(get_session().get_tempfile_path(t), |
|
1120 |
content_type=tempfile['content_type']) |
|
1121 | 1121 |
except misc.ThumbnailError: |
1122 | 1122 |
pass |
1123 | 1123 |
else: |
1124 | 1124 |
response.set_content_type('image/png') |
1125 | 1125 |
return thumbnail |
1126 |
return file_pointer.read()
|
|
1126 |
return get_session().get_tempfile_content(t).get_file_pointer().read()
|
|
1127 | 1127 | |
1128 | 1128 |
def validating(self, data): |
1129 | 1129 |
self.html_top(self.formdef.name) |
wcs/qommon/form.py | ||
---|---|---|
71 | 71 |
from qommon import _, ngettext |
72 | 72 |
import misc |
73 | 73 |
from .humantime import humanduration2seconds, seconds2humanduration, timewords |
74 |
from .misc import strftime, C_ |
|
74 |
from .misc import strftime, C_, HAS_GM
|
|
75 | 75 |
from publisher import get_cfg |
76 | 76 |
from .template_utils import render_block_to_string |
77 | 77 | |
... | ... | |
696 | 696 |
if not temp: |
697 | 697 |
return False |
698 | 698 | |
699 |
filetype = mimetypes.guess_type(temp.get('orig_filename', '')) |
|
700 |
if not (filetype and filetype[0] and filetype[0].startswith('image')): |
|
699 |
filetype = (mimetypes.guess_type(temp.get('orig_filename', '')) or [''])[0] |
|
700 |
if filetype == 'application/pdf': |
|
701 |
return HAS_GM |
|
702 | ||
703 |
if not filetype.startswith('image/'): |
|
701 | 704 |
return False |
702 | 705 | |
703 | 706 |
if Image: |
... | ... | |
819 | 822 |
# quack like UploadedFile |
820 | 823 |
return self.get_file_pointer() |
821 | 824 | |
825 |
def get_filename(self): |
|
826 |
if not hasattr(self, 'qfilename'): |
|
827 |
raise AttributeError('filename') |
|
828 |
basedir = os.path.join(get_publisher().app_dir, 'uploads') |
|
829 |
return os.path.join(basedir, self.qfilename) |
|
830 | ||
822 | 831 |
def get_content(self): |
823 | 832 |
if hasattr(self, 'qfilename'): |
824 | 833 |
filename = os.path.join(get_publisher().app_dir, 'uploads', self.qfilename) |
wcs/qommon/misc.py | ||
---|---|---|
51 | 51 |
from urllib2 import urlparse |
52 | 52 |
from cStringIO import StringIO |
53 | 53 | |
54 |
try: |
|
55 |
subprocess.check_call(['which', 'gm'], stdout=open('/dev/null', 'w')) |
|
56 |
HAS_GM = True |
|
57 |
except subprocess.CalledProcessError: |
|
58 |
HAS_GM = False |
|
59 | ||
54 | 60 | |
55 | 61 |
class ThumbnailError(Exception): |
56 | 62 |
pass |
... | ... | |
553 | 559 |
digest.update(chunk) |
554 | 560 |
return digest.hexdigest() |
555 | 561 | |
556 |
def get_thumbnail(fp): |
|
557 |
if Image is None: |
|
562 | ||
563 |
def can_thumbnail(content_type): |
|
564 |
if content_type == 'application/pdf' and not (HAS_GM and Image): |
|
565 |
return False |
|
566 |
if content_type and content_type.startswith('image/'): |
|
567 |
return bool(Image is not None) |
|
568 |
return False |
|
569 | ||
570 | ||
571 |
def get_thumbnail(filepath, content_type=None): |
|
572 |
if not can_thumbnail(content_type or ''): |
|
558 | 573 |
raise ThumbnailError() |
559 | 574 | |
575 |
if content_type == 'application/pdf': |
|
576 |
fp = StringIO(subprocess.check_output( |
|
577 |
['gm', 'convert', '-geometry', '500x', filepath, 'png:-'])) |
|
578 |
else: |
|
579 |
fp = open(filepath) |
|
580 | ||
560 | 581 |
try: |
561 | 582 |
image = Image.open(fp) |
562 | 583 |
image.thumbnail((500, 300)) |
563 | 584 |
image_thumb_fp = StringIO() |
564 | 585 |
image.save(image_thumb_fp, "PNG") |
565 | 586 |
except IOError: |
566 |
# failed to create thumbnail; restore file pointer state and raise |
|
567 |
# exception. |
|
568 |
fp.seek(0) |
|
587 |
# failed to create thumbnail. |
|
569 | 588 |
raise ThumbnailError() |
570 | 589 |
return image_thumb_fp.getvalue() |
571 | 590 |
wcs/qommon/sessions.py | ||
---|---|---|
303 | 303 |
return None |
304 | 304 |
return misc.json_loads(open(filename).read()) |
305 | 305 | |
306 |
def get_tempfile_path(self, token): |
|
307 |
temp = self.get_tempfile(token) |
|
308 |
if not temp: |
|
309 |
return None |
|
310 |
dirname = os.path.join(get_publisher().app_dir, 'tempfiles') |
|
311 |
filename = os.path.join(dirname, temp['unsigned_token']) |
|
312 |
return filename |
|
313 | ||
306 | 314 |
def get_tempfile_content(self, token): |
307 | 315 |
temp = self.get_tempfile(token) |
308 | 316 |
if not temp: |
309 |
- |