3 from zipfile import ZipFile
4 from urllib import quote
5 from django.conf import settings
6 from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
7 from django.utils.decorators import method_decorator
8 from django.views.decorators.vary import vary_on_headers
9 from django.views.generic import FormView, View, RedirectView
10 from .forms import UploadForm
13 # Use sorl.thumbnail if available.
15 from sorl.thumbnail import default
17 def thumbnail(relpath):
18 return settings.MEDIA_URL + relpath
20 def thumbnail(relpath):
22 return default.backend.get_thumbnail(relpath, "x50").url
24 # That's not an image. No thumb.
28 class JSONResponse(HttpResponse):
29 """JSON response class."""
30 def __init__(self, obj='', mimetype="application/json", *args, **kwargs):
31 content = json.dumps(obj)
32 super(JSONResponse, self).__init__(content, mimetype, *args, **kwargs)
34 class UploadViewMixin(object):
35 def get_safe_path(self, filename=""):
36 """Finds absolute filesystem path of the browsed dir of file.
38 Makes sure it's inside MEDIA_ROOT.
41 path = os.path.abspath(os.path.join(
45 if not path.startswith(os.path.abspath(settings.MEDIA_ROOT)):
48 if not path.startswith(self.get_safe_path()):
52 class UploadView(UploadViewMixin, FormView):
53 template_name = "fileupload/picture_form.html"
54 form_class = UploadForm
56 def get_object(self, request, *args, **kwargs):
57 """Get any data for later use."""
60 def get_directory(self):
61 """Directory relative to MEDIA_ROOT. Must end with a slash."""
62 return self.kwargs['path']
64 def breadcrumbs(self):
65 """List of tuples (name, url) or just (name,) for breadcrumbs.
67 Probably only the last item (representing currently browsed dir)
71 directory = self.get_directory()
72 now_path = os.path.dirname(self.request.get_full_path())
73 directory = os.path.dirname(directory)
76 (os.path.basename(directory),)
78 directory = os.path.dirname(directory)
79 now_path = (os.path.dirname(now_path))
81 crumbs.insert(0, (os.path.basename(directory), now_path+'/'))
82 directory = os.path.dirname(directory)
83 now_path = os.path.dirname(now_path)
84 crumbs.insert(0, ('media', now_path))
89 def get_url(self, filename):
90 """Finds URL of a file in browsed dir."""
91 return settings.MEDIA_URL + self.get_directory() + quote(filename.encode('utf-8'))
93 @method_decorator(vary_on_headers('Accept'))
94 def dispatch(self, request, *args, **kwargs):
95 self.object = self.get_object(request, *args, **kwargs)
96 return super(UploadView, self).dispatch(request, *args, **kwargs)
98 def get(self, request, *args, **kwargs):
101 path = self.get_safe_path()
102 if os.path.isdir(path):
103 for f in sorted(os.listdir(path)):
107 if os.path.isdir(os.path.join(path, f)):
109 "url": "%s%s/" % (request.get_full_path(), f),
113 "url": self.get_url(f),
114 'thumbnail_url': thumbnail(self.get_directory() + f),
115 'delete_url': "%s?file=%s" % (
116 request.get_full_path(),
117 quote(f.encode('utf-8'))),
118 'delete_type': "DELETE"
120 thumbnail_url = thumbnail(self.get_directory() + f),
121 files.append(file_info)
122 return JSONResponse(files)
124 return super(UploadView, self).get(request, *args, **kwargs)
126 def form_valid(self, form):
127 flist = self.request.FILES.getlist('files')
128 path = self.get_safe_path()
129 if not os.path.isdir(path):
133 with open(self.get_safe_path(f.name), 'w') as destination:
134 for chunk in f.chunks():
135 destination.write(chunk)
138 'url': self.get_url(f.name),
139 'thumbnail_url': thumbnail(self.get_directory() + f.name),
140 'delete_url': "%s?file=%s" % (
141 self.request.get_full_path(),
142 quote(f.name.encode('utf-8'))),
143 'delete_type': "DELETE"
145 response = JSONResponse(data)
146 response['Content-Disposition'] = 'inline; filename=files.json'
149 def delete(self, request, *args, **kwargs):
150 os.unlink(self.get_safe_path(request.GET.get('file')))
151 response = JSONResponse(True)
152 response['Content-Disposition'] = 'inline; filename=files.json'
156 class PackageView(UploadViewMixin, RedirectView):
157 def dispatch(self, request, *args, **kwargs):
158 self.object = self.get_object(request, *args, **kwargs)
159 path = self.get_safe_path()
160 with ZipFile(os.path.join(path, 'package.zip'), 'w') as zip_file:
161 for f in os.listdir(path):
162 if f == 'package.zip':
164 zip_file.write(os.path.join(path, f), arcname = f)
165 return super(PackageView, self).dispatch(request, *args, **kwargs)