Валидаторы¶
Конструктор Uploader
принимает необязательный аргумент validators
.
Валидатором может быть любой вызываемый объект,
который в качестве единственного аргумента принимает загруженный файл
и в случае ошибки выбрасывает исключение ValidationError
:
# Source code from Flask-Uploader
import typing as t
from werkzeug.datastructures import FileStorage
TValidator = t.Callable[[FileStorage], None]
Все встроенные валидаторы созданы на базе классов
и принимают в конструкторе необязательный аргумент message
,
который можно передать если вы хотите изменить сообщение об ошибке.
FileRequired¶
FileRequired
- проверяет, что файл был выбран и отправлен.
Если файл не выбран в HTML-форме, то Flask создает экземпляр
FileStorage
без имени файла,
явное приведение к логическому типу вернет False
.
На этой логике строится работа данного валидатора:
>>> from werkzeug.datastructures import FileStorage
>>> from flask_uploader.validators import FileRequired
>>> v = FileRequired()
>>> f = FileStorage(name='file', filename='test.txt')
>>> v(f)
>>> f = FileStorage(name='file')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: The file "file" is required.
>>> f = FileStorage(name='file', filename='')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: The file "file" is required.
Extension¶
Extension
- проверяет расширение файла.
Можно использовать определенные в классе константы или их сочетание, либо вручную указать нужные расширения:
>>> from werkzeug.datastructures import FileStorage
>>> from flask_uploader.validators import Extension
>>> v = Extension(Extension.IMAGES)
>>> f = FileStorage(filename='test.jpg')
>>> v(f)
>>> f = FileStorage(filename='test.txt')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: This file type is not allowed to be uploaded.
>>> v = Extension(Extension.TEXT | {'html', 'css'})
>>> f = FileStorage(filename='test')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: The file has no extension.
>>> v = Extension({'mp4', 'mkv'}, message='This is not a video file.')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: This is not a video file.
FileSize¶
FileSize
- проверяет,
что размер файла не больше и, опционально, не меньше заданного.
Размер можно указывать как количество байт целое или дробное,
либо строкой с единицой измерения (регистр значения не имеет):
b
- байтыk
илиkb
- килобайтыm
илиmb
- мегабайтыg
илиgb
- гигабайтыt
илиtb
- терабайтыp
илиpb
- петабайты =)
Если строка содержит не число или не верную единицу измерения, будет выброшено исключение.
>>> from io import BytesIO
>>> from werkzeug.datastructures import FileStorage
>>> from flask_uploader.validators import FileSize
>>> f = FileStorage(BytesIO(b'abcdefg'))
>>> v = FileSize(4)
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: The size of the uploaded file must be between 0.0B and 4.0B.
>>> f = FileStorage(BytesIO(b'abcdefg'))
>>> v = FileSize('4b')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: The size of the uploaded file must be between 0.0B and 4.0B.
>>> f = FileStorage()
>>> v = FileSize(min_size=2, max_size='4b')
>>> v(f)
Traceback (most recent call last):
...
flask_uploader.exceptions.ValidationError: The size of the uploaded file must be between 2.0B and 4.0B.
ImageSize¶
ImageSize
- проверяет размер изображения в пикселях.
Можно отдельно проверить минимальную или максимульную ширину или высоту,
либо любое сочетание этих параметров.
В валидаторе объявлены константы сообщений об ошибках для часто используемых вариантов проверок.
Например:
from flask_uploader.validators import ImageSize
# Точный размер изображения 100x200px
v = ImageSize(
min_width=100, min_height=200,
max_width=100, max_height=200,
message=ImageSize.EXACT_SIZE,
)
# Изображение больше или равно 100x200px
v = ImageSize(
min_width=100, min_height=200,
message=ImageSize.SIZE_GREATER_EQUAL,
)
# Изображение меньше или равно 1920x1080px
v = ImageSize(
max_width=1920, max_height=1080,
message=ImageSize.SIZE_LESS_EQUAL,
)
Новый валидатор¶
Вы можете реализовать абсолютно любой валидатор, например, проверить формат загруженного файла:
import json
from flask_uploader import Uploader
from flask_uploader.validators import ValidationError
def is_json_file(storage: FileStorage) -> None:
try:
json.loads(storage.stream.read()) # Can use a lot of RAM.
storage.stream.seek(0)
except UnicodeDecodeError:
raise ValidationError('This is not a JSON file.')
except MemoryError:
raise ValidationError('The file is too large.')
files_uploader = Uploader(
'files',
FileSystemStorage(dest='files'),
validators=[
is_json_file,
],
)
Если валидатору требуются дополнительные параметры, то реализуйте его с помощью класса, а параметры передайте как аргументы конструктора. Хороший тон, если ваш валидатор может принять необязательный параметр - сообщение об ошибке, чтобы пользователь мог задать свое сообщение. Перепишем ранее рассмотренный валидатор:
import typing as t
class IsJSON:
def __init__(self, message: t.Optional[str] = None) -> None:
self.message = message
def __call__(self, storage: FileStorage) -> None:
try:
json.loads(storage.stream.read()) # Can use a lot of RAM.
storage.stream.seek(0)
except UnicodeDecodeError:
raise ValidationError(
self.message or 'This is not a JSON file.'
)
except MemoryError:
raise ValidationError(
self.message or 'The file is too large.'
)