import os import hashlib import mimetypes from django import forms from django.core.files.storage import default_storage from django.core.exceptions import ValidationError from university.file_storage.utils import generate_random_file_path from university.models import Upload, User class UploadFileForm(forms.Form): file = forms.FileField() def __init__(self, user, *args, **kwargs): self.user = user return super(UploadFileForm, self).__init__(*args, **kwargs) def save(self): file_obj = self.cleaned_data['file'] content_hash = hashlib.sha1(file_obj.read()).hexdigest() content_type, _ = mimetypes.guess_type(file_obj.name, strict=False) file_path = generate_random_file_path() _, file_extension = os.path.splitext(file_obj.name) if file_extension: file_path += file_extension file_obj.seek(0) default_storage.save(file_path, file_obj) return Upload.objects.create( user=self.user, original_filename=file_obj.name, filesize=file_obj.size, path=file_path, sha1=content_hash, extension=content_type ) class UploadFaceIDImageForm(forms.Form): file = forms.ImageField() def __init__(self, user, *args, **kwargs): self.user = user if user.is_authenticated else None return super(UploadFaceIDImageForm, self).__init__(*args, **kwargs) def clean_file(self): file = self.cleaned_data.get('file') if file: try: file._size except Exception: pass else: if file._size > 3 * 1 << 20: raise ValidationError('文件大小超过限制') if self.user.face_audit_status not in ( User.FACE_AUDIT_NO_IMAGE, User.FACE_AUDIT_FAILED): raise ValidationError('当前状态不允许上传图片') return file def save(self): file_obj = self.cleaned_data.get('file') if file_obj: content_hash = hashlib.sha1(file_obj.read()).hexdigest() content_type, _ = mimetypes.guess_type(file_obj.name, strict=False) file_path = self.generate_filepath_by_hash(content_hash) _, file_extension = os.path.splitext(file_obj.name) if file_extension: file_path += file_extension file_obj.seek(0) file_path = default_storage.save(file_path, file_obj) return Upload.objects.create( user=self.user, original_filename=file_obj.name, filesize=file_obj.size, width=file_obj.image.width, height=file_obj.image.height, path=file_path, sha1=content_hash, extension=content_type, is_private=True ) def generate_filepath_by_hash(self, file_hash): return '{}/{}/{}'.format( file_hash[0], file_hash[1], file_hash )