|
|
import hashlib
|
|
|
import os
|
|
|
import time
|
|
|
|
|
|
from random import random
|
|
|
|
|
|
from django.db import models
|
|
|
|
|
|
from boards.models.attachment.viewers import AbstractViewer, WebmViewer
|
|
|
|
|
|
|
|
|
FILES_DIRECTORY = 'files/'
|
|
|
FILE_EXTENSION_DELIMITER = '.'
|
|
|
|
|
|
VIEWERS = (
|
|
|
WebmViewer,
|
|
|
)
|
|
|
|
|
|
|
|
|
class AttachmentManager(models.Manager):
|
|
|
def create_with_hash(self, file):
|
|
|
file_hash = self.get_hash(file)
|
|
|
existing = self.filter(hash=file_hash)
|
|
|
if len(existing) > 0:
|
|
|
attachment = existing[0]
|
|
|
else:
|
|
|
file_type = file.name.split(FILE_EXTENSION_DELIMITER)[-1].lower()
|
|
|
attachment = Attachment.objects.create(file=file,
|
|
|
mimetype=file_type, hash=file_hash)
|
|
|
|
|
|
return attachment
|
|
|
|
|
|
def get_hash(self, file):
|
|
|
"""
|
|
|
Gets hash of an file.
|
|
|
"""
|
|
|
md5 = hashlib.md5()
|
|
|
for chunk in file.chunks():
|
|
|
md5.update(chunk)
|
|
|
return md5.hexdigest()
|
|
|
|
|
|
|
|
|
class Attachment(models.Model):
|
|
|
objects = AttachmentManager()
|
|
|
|
|
|
# TODO Dedup the method
|
|
|
def _update_filename(self, filename):
|
|
|
"""
|
|
|
Gets unique filename
|
|
|
"""
|
|
|
|
|
|
# TODO Use something other than random number in file name
|
|
|
new_name = '{}{}.{}'.format(
|
|
|
str(int(time.mktime(time.gmtime()))),
|
|
|
str(int(random() * 1000)),
|
|
|
filename.split(FILE_EXTENSION_DELIMITER)[-1:][0])
|
|
|
|
|
|
return os.path.join(FILES_DIRECTORY, new_name)
|
|
|
|
|
|
file = models.FileField(upload_to=_update_filename)
|
|
|
mimetype = models.CharField(max_length=50)
|
|
|
hash = models.CharField(max_length=36)
|
|
|
|
|
|
def get_view(self):
|
|
|
file_viewer = None
|
|
|
for viewer in VIEWERS:
|
|
|
if viewer.supports(self.mimetype):
|
|
|
file_viewer = viewer(self.file, self.mimetype)
|
|
|
break
|
|
|
if file_viewer is None:
|
|
|
file_viewer = AbstractViewer(self.file, self.mimetype)
|
|
|
|
|
|
return file_viewer.get_view()
|
|
|
|
|
|
|
|
|
|