-
Notifications
You must be signed in to change notification settings - Fork 98
/
Copy path__init__.py
102 lines (85 loc) · 3.46 KB
/
__init__.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
VERSION = (0, 3, 11)
__version__ = '.'.join(map(str, VERSION))
import os.path
from mimetypes import guess_type
import unicodedata
def _lazy_load(fn):
_cached = []
def _decorated():
if not _cached:
_cached.append(fn())
return _cached[0]
def clear():
while _cached:
_cached.pop()
_decorated.clear = clear
return _decorated
@_lazy_load
def _get_sendfile():
try:
from importlib import import_module
except ImportError:
from django.utils.importlib import import_module
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
backend = getattr(settings, 'SENDFILE_BACKEND', None)
if not backend:
raise ImproperlyConfigured('You must specify a value for SENDFILE_BACKEND')
module = import_module(backend)
return module.sendfile
def sendfile(request, filename, attachment=False, attachment_filename=None, mimetype=None, encoding=None):
'''
create a response to send file using backend configured in SENDFILE_BACKEND
If attachment is True the content-disposition header will be set.
This will typically prompt the user to download the file, rather
than view it. The content-disposition filename depends on the
value of attachment_filename:
None (default): Same as filename
False: No content-disposition filename
String: Value used as filename
If no mimetype or encoding are specified, then they will be guessed via the
filename (using the standard python mimetypes module)
'''
_sendfile = _get_sendfile()
if not os.path.exists(filename):
from django.http import Http404
raise Http404('"%s" does not exist' % filename)
guessed_mimetype, guessed_encoding = guess_type(filename)
if mimetype is None:
if guessed_mimetype:
mimetype = guessed_mimetype
else:
mimetype = 'application/octet-stream'
response = _sendfile(request, filename, mimetype=mimetype)
if attachment:
if attachment_filename is None:
attachment_filename = os.path.basename(filename)
parts = ['attachment']
if attachment_filename:
try:
from django.utils.encoding import force_str as force_text
except ImportError:
# Django 2.x
try:
from django.utils.encoding import force_text
except ImportError:
# Django 1.3
from django.utils.encoding import force_unicode as force_text
attachment_filename = force_text(attachment_filename)
ascii_filename = force_text(unicodedata.normalize('NFKD', attachment_filename).encode('ascii','ignore'))
parts.append('filename="%s"' % ascii_filename)
if ascii_filename != attachment_filename:
try:
from urllib.parse import quote as urlquote
except ImportError:
from django.utils.http import urlquote
quoted_filename = urlquote(attachment_filename)
parts.append('filename*=UTF-8\'\'%s' % quoted_filename)
response['Content-Disposition'] = '; '.join(parts)
response['Content-length'] = os.path.getsize(filename)
response['Content-Type'] = mimetype
if not encoding:
encoding = guessed_encoding
if encoding:
response['Content-Encoding'] = encoding
return response