101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
from nicegui import ui
|
|
from typing import Dict, Any, List
|
|
import base64
|
|
from PIL import Image
|
|
import io
|
|
from niceguiex.components import FileDrop, ImageDrop
|
|
from niceguiex.components.file_drop import FileData, ImageData
|
|
|
|
|
|
@ui.page('/')
|
|
async def main_page():
|
|
ui.label('File Drop Demo').classes('text-h4 mb-4')
|
|
|
|
# Example 1: Multiple files with content
|
|
uploaded_files = ui.column().classes('w-full mt-4')
|
|
|
|
def handle_multiple_files(file: FileData):
|
|
with uploaded_files:
|
|
with ui.card().classes('p-2 mb-2'):
|
|
ui.label(f"📄 {file['name']}").classes('font-medium')
|
|
ui.label(f"Size: {file['size']:,} bytes").classes('text-sm text-gray-600')
|
|
ui.label(f"Type: {file['file_type']}").classes('text-sm text-gray-600')
|
|
|
|
ui.label('Multiple Files (returns list)').classes('text-h6 mb-2')
|
|
FileDrop(
|
|
on_upload=handle_multiple_files,
|
|
multiple=True,
|
|
accept='.pdf,.docx,.txt,.jpg,.png',
|
|
max_size=5 # 5MB limit
|
|
).classes('w-full max-w-xl mx-auto')
|
|
|
|
ui.separator().classes('my-8')
|
|
|
|
# Example 2: Single file (returns dict directly)
|
|
single_file_info = ui.column().classes('w-full mt-4')
|
|
|
|
def handle_single_file(file: Dict[str, Any]):
|
|
single_file_info.clear()
|
|
with single_file_info:
|
|
ui.label(f"Single file uploaded: {file['name']}").classes('font-bold')
|
|
ui.label(f"Size: {file['size']:,} bytes")
|
|
|
|
ui.label('Single File (returns dict)').classes('text-h6 mb-2')
|
|
FileDrop(
|
|
on_upload=handle_single_file,
|
|
multiple=False,
|
|
accept='.pdf,.docx,.txt'
|
|
).classes('w-full max-w-xl mx-auto')
|
|
|
|
ui.separator().classes('my-8')
|
|
|
|
# Example 3: Large files with temp path
|
|
large_file_info = ui.column().classes('w-full mt-4')
|
|
|
|
def handle_large_file(file: Dict[str, Any]):
|
|
large_file_info.clear()
|
|
with large_file_info:
|
|
ui.label(f"Large file saved to: {file['path']}").classes('font-bold')
|
|
ui.label(f"Name: {file['name']}")
|
|
ui.label(f"Size: {file['size']:,} bytes")
|
|
|
|
ui.label('Large Files (returns temp path)').classes('text-h6 mb-2')
|
|
FileDrop(
|
|
on_upload=handle_large_file,
|
|
multiple=False,
|
|
return_content=False, # Returns path instead of content
|
|
accept='video/*'
|
|
).classes('w-full max-w-xl mx-auto')
|
|
|
|
ui.separator().classes('my-8')
|
|
|
|
# Example 4: Image drop with preview
|
|
image_preview = ui.column().classes('w-full mt-4')
|
|
|
|
def handle_image(img: ImageData):
|
|
print(f"Image uploaded: {img['image'].format}, Size: {img['size']}")
|
|
image_preview.clear()
|
|
with image_preview:
|
|
ui.label(f"Image: {img['image'].format} - {img['image'].size[0]}x{img['image'].size[1]}px").classes('mb-2')
|
|
# Convert PIL image back to base64 for display
|
|
buffered = io.BytesIO()
|
|
img['image'].save(buffered, format=img['image'].format or 'PNG')
|
|
img_data = base64.b64encode(buffered.getvalue()).decode()
|
|
ui.html(f'<img src="data:image/{img['image'].format.lower() if img['image'].format else "png"};base64,{img_data}" class="max-w-full rounded">')
|
|
|
|
ui.label('Image Drop (returns PIL Image)').classes('text-h6 mb-2')
|
|
ImageDrop(
|
|
on_upload=handle_image,
|
|
multiple=False,
|
|
max_size=15 # 15MB limit for images
|
|
).classes('w-full max-w-xl mx-auto').style('min-height: 150px')
|
|
|
|
if __name__ in {"__main__", "__mp_main__"}:
|
|
ui.run(
|
|
title='File Drop Demo',
|
|
favicon='📁',
|
|
show=False,
|
|
dark=False,
|
|
port=8083
|
|
)
|