-
Notifications
You must be signed in to change notification settings - Fork 1
/
models.py
139 lines (114 loc) · 4.05 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# coding=utf-8
import os
import uuid
from datetime import datetime
try:
from urllib import quote
except ImportError:
from urllib.parse import quote
import cropresize2
import short_url
from PIL import Image
from flask import abort, request
from werkzeug.utils import cached_property
from mimes import IMAGE_MIMES, AUDIO_MIMES, VIDEO_MIMES
from utils import get_file_path, get_file_md5
from app import app, db
class File(db.Model):
__tablename__ = 'File'
id = db.Column(db.Integer, primary_key=True)
filename = db.Column(db.String(500), nullable=False)
filehash = db.Column(db.String(128), nullable=False, unique=True)
filemd5 = db.Column(db.String(128), nullable=False, unique=True)
uploadtime = db.Column(db.DateTime, default=datetime.now(), nullable=False)
mimetype = db.Column(db.String(256), nullable=False)
size = db.Column(db.Integer, nullable=False)
def __init__(self, filename='', mimetype='application/octet-stream',
size=0, filehash=None, filemd5=None):
self.mimetype = mimetype
self.size = int(size)
self.filehash = filehash if filehash else self._hash_filename(filename)
self.filename = filename if filename else self.filehash
self.filemd5 = filemd5
@staticmethod
def _hash_filename(filename):
_, _, suffix = filename.rpartition('.')
return "{}.{}".format(uuid.uuid4().hex, suffix)
@cached_property
def symlink(self):
return short_url.encode_url(self.id)
@classmethod
def get_by_md5(cls, filemd5):
return cls.query.filter_by(filemd5=filemd5).first()
@classmethod
def get_by_filehash(cls, filehash, code=404):
return cls.query.filter_by(filehash=filehash).first() or abort(code)
@classmethod
def get_by_symlink(cls, symlink, code=404):
id = short_url.decode_url(symlink)
return cls.query.filter_by(id=id).first() or abort(code)
@property
def path(self):
return get_file_path(self.filehash)
@classmethod
def create_by_upload_file(cls, upload_file):
rst = cls(upload_file.filename, upload_file.mimetype, 0)
upload_file.save(rst.path)
with open(rst.path, 'rb') as f:
filemd5 = get_file_md5(f)
upload_file = cls.get_by_md5(filemd5)
if upload_file:
os.remove(rst.path)
return upload_file
filestat = os.stat(rst.path)
rst.size = filestat.st_size
rst.filemd5 = filemd5
return rst
@classmethod
def rsize(cls, old_paste, weight, height):
assert old_paste.is_image, TypeError('Unsuppoprted Image Type')
img = cropresize2.crop_resize(
Image.open(old_paste.path), (int(weight), int(height))
)
rst = cls(old_paste.filename, old_paste.mimetype, 0)
img.save(rst.path)
filestat = os.stat(rst.path)
rst.size = filestat.st_size
return rst
@property
def is_image(self):
return self.mimetype in IMAGE_MIMES
@property
def is_video(self):
return self.mimetype in VIDEO_MIMES
@property
def is_audio(self):
return self.mimetype in AUDIO_MIMES
@property
def is_pdf(self):
return self.mimetype == 'application/pdf'
@property
def type(self):
for t in ('image', 'pdf', 'video', 'audio'):
if getattr(self, 'is_' + t):
return t
return 'binary'
@property
def quoteurl(self):
return quote(self.url_i)
def get_url(self, subtype, is_symlink=False):
hash_or_link = self.symlink if is_symlink else self.filehash
return 'http://{host}/{subtype}/{hash_or_link}'.format(subtype=subtype, host=request.host,
hash_or_link=hash_or_link)
@property
def url_i(self):
return self.get_url('i')
@property
def url_p(self):
return self.get_url('p')
@property
def url_s(self):
return self.get_url('s')
@property
def url_d(self):
return self.get_url('d')