You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
3.0 KiB
74 lines
3.0 KiB
from typing import Any, Callable, Dict, Optional |
|
|
|
from fastapi import Request |
|
from starlette.datastructures import UploadFile |
|
|
|
from ..events import UiEventArguments, UploadEventArguments, handle_event |
|
from ..nicegui import app |
|
from .mixins.disableable_element import DisableableElement |
|
|
|
|
|
class Upload(DisableableElement, component='upload.js'): |
|
|
|
def __init__(self, *, |
|
multiple: bool = False, |
|
max_file_size: Optional[int] = None, |
|
max_total_size: Optional[int] = None, |
|
max_files: Optional[int] = None, |
|
on_upload: Optional[Callable[..., Any]] = None, |
|
on_rejected: Optional[Callable[..., Any]] = None, |
|
label: str = '', |
|
auto_upload: bool = False, |
|
) -> None: |
|
"""File Upload |
|
|
|
Based on Quasar's `QUploader <https://quasar.dev/vue-components/uploader>`_ component. |
|
|
|
:param multiple: allow uploading multiple files at once (default: `False`) |
|
:param max_file_size: maximum file size in bytes (default: `0`) |
|
:param max_total_size: maximum total size of all files in bytes (default: `0`) |
|
:param max_files: maximum number of files (default: `0`) |
|
:param on_upload: callback to execute for each uploaded file (type: nicegui.events.UploadEventArguments) |
|
:param on_rejected: callback to execute for each rejected file |
|
:param label: label for the uploader (default: `''`) |
|
:param auto_upload: automatically upload files when they are selected (default: `False`) |
|
""" |
|
super().__init__() |
|
self._props['multiple'] = multiple |
|
self._props['label'] = label |
|
self._props['auto-upload'] = auto_upload |
|
self._props['url'] = f'/_nicegui/client/{self.client.id}/upload/{self.id}' |
|
|
|
if max_file_size is not None: |
|
self._props['max-file-size'] = max_file_size |
|
|
|
if max_total_size is not None: |
|
self._props['max-total-size'] = max_total_size |
|
|
|
if max_files is not None: |
|
self._props['max-files'] = max_files |
|
|
|
@app.post(self._props['url']) |
|
async def upload_route(request: Request) -> Dict[str, str]: |
|
for data in (await request.form()).values(): |
|
assert isinstance(data, UploadFile) |
|
args = UploadEventArguments( |
|
sender=self, |
|
client=self.client, |
|
content=data.file, |
|
name=data.filename or '', |
|
type=data.content_type or '', |
|
) |
|
handle_event(on_upload, args) |
|
return {'upload': 'success'} |
|
|
|
if on_rejected: |
|
self.on('rejected', lambda _: handle_event(on_rejected, UiEventArguments(sender=self, client=self.client)), |
|
args=[]) |
|
|
|
def reset(self) -> None: |
|
self.run_method('reset') |
|
|
|
def _on_delete(self) -> None: |
|
app.remove_route(self._props['url']) |
|
super()._on_delete()
|
|
|