forked from fhanspach/thmbnlr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
131 lines (100 loc) · 3.42 KB
/
main.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
try:
from StringIO import StringIO
except ImportError:
from io import BytesIO as StringIO
import sys
import requests
from flask import Flask, send_file, request, redirect, jsonify, render_template
from PIL import Image
import os
app = Flask(__name__)
ERR_URL_MISSING = "URL must not be None!"
ERR_URL_IS_NOT_AN_IMAGE = "Not an image!"
DEBUG = os.environ.get('THMBNLR_DEBUG', False)
HOST = os.environ.get('HOST', '127.0.0.1')
@app.route("/")
def get_image():
get_query = request.args.to_dict(flat=True)
url = get_query.pop('url', None)
if not url:
return render_template("landing_page.html"), 400
thmbnlr = Thmbnlr(url, **get_query)
try:
result = thmbnlr()
except requests.exceptions.HTTPError as e:
return jsonify(**{"request_url": e.request.url, "status_code": e.response.status_code}), e.response.status_code
return result
class Thmbnlr():
def __init__(self, url, width=sys.maxsize, height=sys.maxsize, quality=100, max_size=0, **kwargs):
self.url = url
self.width = int(width)
self.height = int(height)
self._quality = int(quality)
self.max_size = int(max_size)
self._head = None
self._image = None
def __call__(self):
if not self.check_if_image():
return ERR_URL_IS_NOT_AN_IMAGE
in_size = self.check_file_size()
if (self.height == sys.maxsize and self.width == sys.maxsize and self.quality == 100) or in_size:
return redirect(self.url)
img_io = self.resize_image()
return send_file(img_io, mimetype=self.content_type)
def resize_image(self):
size = (self.width, self.height)
img = Image.open(StringIO(self.image))
img_io = StringIO()
img.thumbnail(size, Image.ANTIALIAS)
img.save(img_io, format=self.file_type, quality=self.quality)
img_io.seek(0)
return img_io
def check_file_size(self):
response_size = self.file_size
return int(response_size) <= self.max_size_in_bytes
def check_if_image(self):
return self.response_type == "image"
@property
def file_type(self):
_, file_type = self.content_type.split('/')
return file_type
@property
def response_type(self):
response_type, _ = self.content_type.split('/')
return response_type
@property
def content_type(self):
headers = self.head.headers
content_type = headers.get("content-type")
return content_type
@property
def max_size_in_bytes(self):
if self.max_size == 0:
return 0
return self.max_size * 1024
@property
def quality(self):
if self._quality > 100:
return 100
elif self._quality < 0:
return 0
return self._quality
@property
def head(self):
if not self._head:
self._head = requests.head(self.url, allow_redirects=True)
self._head.raise_for_status()
return self._head
@property
def image(self):
if not self._image:
self._image = requests.get(self.url, allow_redirects=True)
self._image.raise_for_status()
return self._image.content
@property
def file_size(self):
headers = self.head.headers
response_size = headers.get('Content-Length', sys.maxsize)
return response_size
if __name__ == "__main__":
app.run(debug=DEBUG, host=HOST)