##// END OF EJS Templates
Added basic SVG support
neko259 -
r1284:aa3c5b96 default
parent child Browse files
Show More
@@ -1,76 +1,77 b''
1 import hashlib
1 import hashlib
2 import os
2 import os
3 import time
3 import time
4
4
5 from random import random
5 from random import random
6
6
7 from django.db import models
7 from django.db import models
8
8
9 from boards.models.attachment.viewers import AbstractViewer, WebmViewer, \
9 from boards.models.attachment.viewers import AbstractViewer, WebmViewer, \
10 AudioViewer
10 AudioViewer, SvgViewer
11
11
12 FILES_DIRECTORY = 'files/'
12 FILES_DIRECTORY = 'files/'
13 FILE_EXTENSION_DELIMITER = '.'
13 FILE_EXTENSION_DELIMITER = '.'
14
14
15 VIEWERS = (
15 VIEWERS = (
16 WebmViewer,
16 WebmViewer,
17 AudioViewer,
17 AudioViewer,
18 SvgViewer,
18 )
19 )
19
20
20
21
21 class AttachmentManager(models.Manager):
22 class AttachmentManager(models.Manager):
22 def create_with_hash(self, file):
23 def create_with_hash(self, file):
23 file_hash = self.get_hash(file)
24 file_hash = self.get_hash(file)
24 existing = self.filter(hash=file_hash)
25 existing = self.filter(hash=file_hash)
25 if len(existing) > 0:
26 if len(existing) > 0:
26 attachment = existing[0]
27 attachment = existing[0]
27 else:
28 else:
28 file_type = file.name.split(FILE_EXTENSION_DELIMITER)[-1].lower()
29 file_type = file.name.split(FILE_EXTENSION_DELIMITER)[-1].lower()
29 attachment = Attachment.objects.create(file=file,
30 attachment = Attachment.objects.create(file=file,
30 mimetype=file_type, hash=file_hash)
31 mimetype=file_type, hash=file_hash)
31
32
32 return attachment
33 return attachment
33
34
34 def get_hash(self, file):
35 def get_hash(self, file):
35 """
36 """
36 Gets hash of an file.
37 Gets hash of an file.
37 """
38 """
38 md5 = hashlib.md5()
39 md5 = hashlib.md5()
39 for chunk in file.chunks():
40 for chunk in file.chunks():
40 md5.update(chunk)
41 md5.update(chunk)
41 return md5.hexdigest()
42 return md5.hexdigest()
42
43
43
44
44 class Attachment(models.Model):
45 class Attachment(models.Model):
45 objects = AttachmentManager()
46 objects = AttachmentManager()
46
47
47 # TODO Dedup the method
48 # TODO Dedup the method
48 def _update_filename(self, filename):
49 def _update_filename(self, filename):
49 """
50 """
50 Gets unique filename
51 Gets unique filename
51 """
52 """
52
53
53 # TODO Use something other than random number in file name
54 # TODO Use something other than random number in file name
54 new_name = '{}{}.{}'.format(
55 new_name = '{}{}.{}'.format(
55 str(int(time.mktime(time.gmtime()))),
56 str(int(time.mktime(time.gmtime()))),
56 str(int(random() * 1000)),
57 str(int(random() * 1000)),
57 filename.split(FILE_EXTENSION_DELIMITER)[-1:][0])
58 filename.split(FILE_EXTENSION_DELIMITER)[-1:][0])
58
59
59 return os.path.join(FILES_DIRECTORY, new_name)
60 return os.path.join(FILES_DIRECTORY, new_name)
60
61
61 file = models.FileField(upload_to=_update_filename)
62 file = models.FileField(upload_to=_update_filename)
62 mimetype = models.CharField(max_length=50)
63 mimetype = models.CharField(max_length=50)
63 hash = models.CharField(max_length=36)
64 hash = models.CharField(max_length=36)
64
65
65 def get_view(self):
66 def get_view(self):
66 file_viewer = None
67 file_viewer = None
67 for viewer in VIEWERS:
68 for viewer in VIEWERS:
68 if viewer.supports(self.mimetype):
69 if viewer.supports(self.mimetype):
69 file_viewer = viewer(self.file, self.mimetype)
70 file_viewer = viewer(self.file, self.mimetype)
70 break
71 break
71 if file_viewer is None:
72 if file_viewer is None:
72 file_viewer = AbstractViewer(self.file, self.mimetype)
73 file_viewer = AbstractViewer(self.file, self.mimetype)
73
74
74 return file_viewer.get_view()
75 return file_viewer.get_view()
75
76
76
77
@@ -1,50 +1,62 b''
1 from django.template.defaultfilters import filesizeformat
1 from django.template.defaultfilters import filesizeformat
2 from django.templatetags.static import static
2 from django.templatetags.static import static
3
3
4 FILE_STUB_IMAGE = 'images/file.png'
4 FILE_STUB_IMAGE = 'images/file.png'
5
5
6 FILE_TYPE_WEBM = 'webm'
6 FILE_TYPE_WEBM = 'webm'
7 FILE_TYPE_SVG = 'svg'
7 FILE_TYPES_AUDIO = (
8 FILE_TYPES_AUDIO = (
8 'ogg',
9 'ogg',
9 'mp3',
10 'mp3',
10 )
11 )
11
12
12
13
13 class AbstractViewer:
14 class AbstractViewer:
14 def __init__(self, file, file_type):
15 def __init__(self, file, file_type):
15 self.file = file
16 self.file = file
16 self.file_type = file_type
17 self.file_type = file_type
17
18
18 @staticmethod
19 @staticmethod
19 def supports(file_type):
20 def supports(file_type):
20 return True
21 return True
21
22
22 def get_view(self):
23 def get_view(self):
23 return '<div class="image"><a href="{}">'\
24 return '<div class="image"><a href="{}">'\
24 '<img src="{}" width="200" height="150"/>'\
25 '<img src="{}" width="200" height="150"/>'\
25 '</a>'\
26 '</a>'\
26 '<div class="image-metadata">{}, {}</div>'\
27 '<div class="image-metadata">{}, {}</div>'\
27 '</div>'.format(self.file.url, static(FILE_STUB_IMAGE),
28 '</div>'.format(self.file.url, static(FILE_STUB_IMAGE),
28 self.file_type, filesizeformat(self.file.size))
29 self.file_type, filesizeformat(self.file.size))
29
30
30
31
31 class WebmViewer(AbstractViewer):
32 class WebmViewer(AbstractViewer):
32 @staticmethod
33 @staticmethod
33 def supports(file_type):
34 def supports(file_type):
34 return file_type == FILE_TYPE_WEBM
35 return file_type == FILE_TYPE_WEBM
35
36
36 def get_view(self):
37 def get_view(self):
37 return '<div class="image">'\
38 return '<div class="image">'\
38 '<video width="200" height="150" controls src="{}"/>'\
39 '<video width="200" height="150" controls src="{}"/>'\
39 '</div>'.format(self.file.url)
40 '</div>'.format(self.file.url)
40
41
41
42
42 class AudioViewer(AbstractViewer):
43 class AudioViewer(AbstractViewer):
43 @staticmethod
44 @staticmethod
44 def supports(file_type):
45 def supports(file_type):
45 return file_type in FILE_TYPES_AUDIO
46 return file_type in FILE_TYPES_AUDIO
46
47
47 def get_view(self):
48 def get_view(self):
48 return '<div class="image">' \
49 return '<div class="image">' \
49 '<audio controls src="{}"/>' \
50 '<audio controls src="{}"/>' \
50 '</div>'.format(self.file.url)
51 '</div>'.format(self.file.url)
52
53
54 class SvgViewer(AbstractViewer):
55 @staticmethod
56 def supports(file_type):
57 return file_type == FILE_TYPE_SVG
58
59 def get_view(self):
60 return '<div class="image">'\
61 '<img width="200" height="150" src="{}"/>'\
62 '</div>'.format(self.file.url)
General Comments 0
You need to be logged in to leave comments. Login now