Flask-Uploader¶
Document version: 0.2.1.dev11
Flask-Uploader - загрузчик файлов для Flask с гибкой возможностью расширения.
Быстрый старт¶
Установка¶
Установите последнюю стабильную версию, выполнив команду:
pip install Flask-Uploader
Или установите последнюю тестовую версию, которая может и будет содержать баги =) Она автоматически собирается и публикуется на test.pypi.org:
pip install \
-i https://test.pypi.org/simple/ \
-i https://pypi.python.org/simple \
Flask-Uploader
Конфигурация¶
Flask-Uploader
использует для инициализации функцию init_uploader()
(это разрешено правилами разработки расширений для Flask).
Вызвать эту фукнцию можно в любом месте, обычно это:
фабричная функция, которая возвращает экземпляр приложения (предпочтительный вариант)
модуль с экземплярами всех используемых расширений
модуль, в котором вы создаете экземпляр приложения (худший вариант)
# Module that contains a factory function
from flask import Flask
from flask_uploader import init_uploader
def create_app():
app = Flask(__name__, instance_relative_config=True)
# Reading and setting configuration options
init_uploader(app)
# Initializing everything you need
return app
Следующие конфигурационные опции доступны для установки:
Опция |
Описание |
---|---|
UPLOADER_ROOT_DIR |
Корневая директория для загруженных файлов.
Должна существовать и иметь права на запись.
По-умолчанию |
UPLOADER_INSTANCE_RELATIVE_ROOT |
Если истина, то |
UPLOADER_BLUEPRINT_NAME |
Программное имя, используемое
внутренним Blueprint.
По-умолчанию |
UPLOADER_BLUEPRINT_URL_PREFIX |
URL префикс, используемый
внутренним Blueprint.
По-умолчанию |
UPLOADER_BLUEPRINT_SUBDOMAIN |
Имя поддомена, используемое
внутренним Blueprint.
По-умолчанию |
UPLOADER_DEFAULT_ENDPOINT |
Имя входной точки для доступа к загруженному файлу,
используемое
внутренним Blueprint.
По-умолчанию |
Создание загрузчика¶
Загрузчик - это экземпляр класса Uploader
.
Цели загрузчика:
валидация загруженного файла
сохранение загруженного файла в хранилище
чтение файла из хранилища по уникальному идентификатору
удаление файла из хранилища по уникальному идентификатору
получение URL-адреса для доступа к загруженному файлу
В первом аргументе конструктора нужно передать уникальное имя. Это имя используется в маршруте по-умолчанию и для получения ранее созданного экземпляра загрузчика.
Во втором аргументе конструктора необходимо передать экземпляр выбранного хранилища.
Остальные аргументы конструктора являются необязательными, однако помните, что первое правило разработчика - «не доверять пользователю», поэтому любые входные данные должны быть отвалидированы.
По-умолчанию именованный аргумент validators
конструктора пустой.
Это означает, что загрузчик разрешает любой файл.
Обязательно передайте значение этого аргумента в зависимости от вашей задачи.
В примере мы создаем загрузчик с именем photos
,
который будет сохранять загруженные файлы на жестком диске относительно корня директории,
заданной конфигурационной опцией UPLOADER_ROOT_DIR
в поддиректории photos
.
Разрешены только файлы изображений не более 10Mb и размером 1920х1080px,
для всех остальных файлов будет выброшено исключение
ValidationError
.
# Module with endpoint handlers, for example - routes/photos.py
from flask_uploader import Uploader
from flask_uploader.storages import FileSystemStorage
from flask_uploader.validators import (
Extension,
ImageSize,
FileRequired,
FileSize,
)
photos_storage = FileSystemStorage(dest='photos')
photos_uploader = Uploader(
'photos',
photos_storage,
validators=[
FileRequired(),
FileSize('10Mb'),
Extension(Extension.IMAGES),
ImageSize(max_width=1920, max_height=1080),
]
)
Поиск загрузчика¶
Экземпляр загрузчика можно создать в любом удобном для вас месте,
а затем в обработчике входной точки получить ранее созданный экземпляр с помощью статического метода
get_instance()
:
from flask_uploader import Uploader
photos_uploader = Uploader.get_instance('photos')
Входная точка¶
Дополним наш пример обработчиком входной точки для загрузки изображений:
# Continuation of the routes/photos.py module
from flask import Blueprint, flash, redirect, request
from flask_uploader.exceptions import UploadNotAllowed
bp = Blueprint('photos', __name__, url_prefix='/photos')
@bp.route('/', methods=['POST'])
def upload():
if 'file' not in request.files:
flash('No file part.')
return redirect(request.url)
try:
lookup = photos_uploader.save(request.files['file'])
flash(f'Photo saved successfully - {lookup}.')
except UploadNotAllowed as err:
flash(str(err))
return redirect(request.url)
Доступ к файлу¶
Flask-Uploader
создает экземпляр Blueprint
для регистрации обработчиков конечных точек по-умолчанию.
Доступ по-умолчанию¶
/<name>/<path:lookup>
- маршрут по-умолчанию для доступа к загруженному файлу,
где name
это уникальное имя загрузчика, а lookup
- уникальный идентификатор файла,
используемый для поиска в выбранном хранилище.
В примере с фотографиями, загруженный файл будет доступен для скачивания по адресу:
http://127.0.0.1:5000/media/photos/<lookup>
lookup - имеет строковой тип даных, в большинстве случаев это относительный путь к файлу,
поэтому в маршруте используется URL-конвертер PathConverter
.
Запрет доступа¶
Если вам нужно запретить публичный доступ к загруженным файлам для маршрута по-умолчанию,
то в момент создания экземпляра Uploader
в конструктор
передайте аргумент use_auto_route
со значением False
:
# Module with endpoint handlers, for example - routes/payments.py
from flask_uploader import Uploader
from flask_uploader.storages import FileSystemStorage
from flask_uploader.validators import Extension
payments_uploader = Uploader(
'payments',
FileSystemStorage(dest='payments'),
use_auto_route=False,
validators=[
Extension(
Extension.IMAGES | Extension.EDOCUMENTS
),
]
)
Контроль доступа¶
Доступ к загруженному файлу можно контролировать, это может быть полезно в следующих случаях:
нужно изменить публичный URL-адрес
запретить доступ для неаутентифицированных пользователей
использовать промежуточное ПО или HTTP-сервер для обслуживания файлов
Для этого в момент создания экземпляра Uploader
в конструктор
передайте аргумент endpoint
с именем конечной точки, включая имена всех Blueprint.
Используйте представление DownloadView
для описания конечной точки:
# Module with endpoint handlers, for example - routes/invoices.py
from flask import Blueprint
from flask_login import login_required
from flask_uploader import Uploader
from flask_uploader.storages import FileSystemStorage
from flask_uploader.validators import Extension
from flask_uploader.views import DownloadView
bp = Blueprint('invoices', __name__, url_prefix='/invoices')
invoices_storage = FileSystemStorage(dest='invoices')
invoices_uploader = Uploader(
'invoices',
invoices_storage,
endpoint='invoices.download',
validators=[
Extension(
Extension.OFFICE
),
]
)
class DownloadInvoiceView(DownloadView):
decorators = [login_required]
uploader_or_name = invoices_uploader
download_endpoint = DownloadInvoiceView.as_view('download')
bp.add_url_rule('/<path:lookup>', view_func=download_endpoint)
Промежуточное ПО¶
Чтобы отдать загруженные файлы, используя промежуточное ПО, например Nginx,
в конфигурационном файле вирутального хоста определите новое правило (location
),
которое перекрывает маршрут по-умолчанию:
# Part of the virtual host configuration file
client_max_body_size 100m;
location /media/photos/ {
rewrite ^/media/(.*)$ /$1 break;
root /path/to/uploader_root_dir;
}
Удаление файла¶
По-умолчанию удаление файла недоступно, это сделано из соображений безопасности.
Используйте представление DestroyView
для описания конечной точки:
# Continuation of the routes/invoices.py module
from flask_uploader.views import DownloadView
class DeleteInvoiceView(DestroyView):
decorators = [login_required]
uploader_or_name = invoices_uploader
delete_endpoint = DeleteInvoiceView.as_view('remove')
bp.add_url_rule('/remove/<path:lookup>', view_func=delete_endpoint)