diff --git a/.gitignore b/.gitignore index 7230e12f66c4c676e29c1c6a86a1fbaa7aaedd4c..a988c9e7f36bc5b8099b76117e708f4c45754dec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ env/* # Folder with db statics (dev mode) smash/~/ +# files uploaded and hosted by django +smash/uploads/ + # Disable python bytecode *.pyc #vim swap files diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py index 57794ce9ed36fd7287d221e1b64add2bdfeab395..5db58bb977dc42c08b437e45c91ca1e542e8be0b 100644 --- a/smash/web/models/constants.py +++ b/smash/web/models/constants.py @@ -1,6 +1,8 @@ # coding=utf-8 import locale +from django.core.files.storage import FileSystemStorage + BOOL_CHOICES = ((True, 'Yes'), (False, 'No')) SEX_CHOICES_MALE = 'M' SEX_CHOICES_FEMALE = 'F' @@ -90,3 +92,5 @@ VOUCHER_STATUS_CHOICES = ( (VOUCHER_STATUS_USED, 'Used'), (VOUCHER_STATUS_EXPIRED, 'Expired'), ) + +FILE_STORAGE = FileSystemStorage(location='uploads') diff --git a/smash/web/urls.py b/smash/web/urls.py index 1ee0abb3b5510f17ced9243d6cec7f7c15543f5a..567ef50b4e736c0d4b80d319f9592ef508be8b66 100644 --- a/smash/web/urls.py +++ b/smash/web/urls.py @@ -206,6 +206,12 @@ urlpatterns = [ url(r'^configuration$', views.configuration_item.configuration_items, name='web.views.configuration'), + #################### + # FILES # + #################### + + url(r'^files/', views.uploaded_files.download, name='web.views.uploaded_files'), + #################### # AUTH # #################### diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py index 6f232ada314602f128abdad7dc2601e2c153f42d..296d4e9fdd25fb4324344099abd639f0621246a0 100644 --- a/smash/web/views/__init__.py +++ b/smash/web/views/__init__.py @@ -81,3 +81,4 @@ import voucher import voucher_type import voucher_type_price import redcap +import uploaded_files diff --git a/smash/web/views/uploaded_files.py b/smash/web/views/uploaded_files.py new file mode 100644 index 0000000000000000000000000000000000000000..e20a022a77488aabc8e7365352ff8f3b60990a54 --- /dev/null +++ b/smash/web/views/uploaded_files.py @@ -0,0 +1,25 @@ +# coding=utf-8 +import logging +import ntpath +from wsgiref.util import FileWrapper + +from django.contrib.auth.decorators import login_required +from django.http import HttpResponse + +from web.models.constants import FILE_STORAGE + +logger = logging.getLogger(__name__) + + +def path_to_filename(path): + head, tail = ntpath.split(path) + return tail or ntpath.basename(head) + + +@login_required +def download(request): + if request.GET and request.GET.get('file'): + path = FILE_STORAGE.location + "/" + request.GET.get('file') + response = HttpResponse(FileWrapper(open(path, 'r')), content_type='application/force-download') + response['Content-Disposition'] = 'attachment; filename=%s' % path_to_filename(path) + return response diff --git a/smash/web/widgets/__init__.py b/smash/web/widgets/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/smash/web/widgets/secure_file_widget.py b/smash/web/widgets/secure_file_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..d26d799f1ea97c6414b865633183427ec973bba0 --- /dev/null +++ b/smash/web/widgets/secure_file_widget.py @@ -0,0 +1,26 @@ +import logging + +from django import forms +from django.core.urlresolvers import reverse +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _ + +logger = logging.getLogger(__name__) + + +class SecuredFileWidget(forms.FileInput): + """A FileField Widget that shows secure file link""" + + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + super(SecuredFileWidget, self).__init__(attrs) + + def render(self, name, value, attrs=None): + output = [] + if value and hasattr(value, "url"): + url = reverse('web.views.uploaded_files') + '?file=' + unicode(value) + out = u'<a href="{}">{}</a><br />{} ' + output.append(out.format(url, _(u'Download'), _(u'Change:'))) + output.append(super(SecuredFileWidget, self).render(name, value, attrs)) + return mark_safe(u''.join(output))