forked from plone/plone.namedfile
/
browser.py
75 lines (57 loc) · 2.57 KB
/
browser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from zope.interface import implements
from zope.publisher.interfaces import IPublishTraverse, NotFound
from plone.rfc822.interfaces import IPrimaryFieldInfo
from plone.namedfile.utils import set_headers, stream_data
from Acquisition import aq_base
from Products.Five.browser import BrowserView
class Download(BrowserView):
"""Download a file, via ../context/@@download/fieldname/filename
`fieldname` is the name of an attribute on the context that contains
the file. `filename` is the filename that the browser will be told to
give the file. If not given, it will be looked up from the field.
The attribute under `fieldname` should contain a named (blob) file/image
instance from this package.
If no `fieldname` is supplied, then a default field is looked up through
adaption to `plone.rfc822.interfaces.IPrimaryFieldInfo`.
"""
implements(IPublishTraverse)
def __init__(self, context, request):
super(Download, self).__init__(context, request)
self.fieldname = None
self.filename = None
def publishTraverse(self, request, name):
if self.fieldname is None: # ../@@download/fieldname
self.fieldname = name
elif self.filename is None: # ../@@download/fieldname/filename
self.filename = name
else:
raise NotFound(self, name, request)
return self
def __call__(self):
file = self._getFile()
if not self.filename:
self.filename = getattr(file, 'filename', self.fieldname)
set_headers(file, self.request.response, filename=self.filename)
return stream_data(file)
def _getFile(self):
if not self.fieldname:
info = IPrimaryFieldInfo(self.context, None)
if info is None:
# Ensure that we have at least a filedname
raise NotFound(self, '', self.request)
self.fieldname = info.fieldname
file = info.value
else:
file = getattr(aq_base(self.context), self.fieldname, None)
if file is None:
raise NotFound(self, self.fieldname, self.request)
return file
class DisplayFile(Download):
"""Display a file, via ../context/@@display-file/fieldname/filename
Same as Download, however in this case we don't set the filename so the
browser can decide to display the file instead.
"""
def __call__(self):
file = self._getFile()
set_headers(file, self.request.response)
return stream_data(file)