""" Страница асинхронной загрузки файлов """ import streamlit as st import asyncio import threading import time import json import os from api_client import upload_file_to_api from config import PARSER_TABS # Глобальное хранилище задач (в реальном приложении лучше использовать Redis или БД) TASKS_STORAGE = {} def upload_file_async_background(endpoint, file_data, filename, task_id): """Асинхронная загрузка файла в фоновом режиме""" global TASKS_STORAGE try: # Обновляем статус на "running" TASKS_STORAGE[task_id] = { 'status': 'running', 'filename': filename, 'endpoint': endpoint, 'started_at': time.time(), 'progress': 0 } # Имитируем асинхронную работу time.sleep(1) # Небольшая задержка для демонстрации # Выполняем загрузку result, status = upload_file_to_api(endpoint, file_data, filename) # Сохраняем результат в глобальном хранилище TASKS_STORAGE[task_id] = { 'status': 'completed' if status == 200 else 'failed', 'result': result, 'status_code': status, 'filename': filename, 'endpoint': endpoint, 'started_at': TASKS_STORAGE.get(task_id, {}).get('started_at', time.time()), 'completed_at': time.time(), 'progress': 100 } except Exception as e: # Сохраняем ошибку TASKS_STORAGE[task_id] = { 'status': 'failed', 'error': str(e), 'filename': filename, 'endpoint': endpoint, 'started_at': TASKS_STORAGE.get(task_id, {}).get('started_at', time.time()), 'completed_at': time.time(), 'progress': 0 } def render_async_upload_page(): """Рендер страницы асинхронной загрузки""" st.title("🚀 Асинхронная загрузка файлов") st.markdown("---") st.info(""" **Асинхронная загрузка** позволяет загружать файлы без блокировки интерфейса. После загрузки файл будет обработан в фоновом режиме, а вы сможете отслеживать прогресс на странице "Управление задачами". """) # Выбор парсера st.subheader("📋 Выбор парсера") # Создаем словарь парсеров с их асинхронными эндпоинтами parser_endpoints = { "Сводки ПМ": "/async/svodka_pm/upload-zip", "Сводки СА": "/async/svodka_ca/upload", "Мониторинг топлива": "/async/monitoring_fuel/upload-zip", "Ремонт СА": "/svodka_repair_ca/upload", # Пока синхронный "Статусы ремонта СА": "/statuses_repair_ca/upload", # Пока синхронный "Мониторинг ТЭР": "/monitoring_tar/upload", # Пока синхронный "Операционные справки": "/oper_spravka_tech_pos/upload" # Пока синхронный } selected_parser = st.selectbox( "Выберите тип парсера для загрузки:", list(parser_endpoints.keys()), key="async_parser_select" ) st.markdown("---") # Загрузка файла st.subheader("📤 Загрузка файла") uploaded_file = st.file_uploader( f"Выберите ZIP архив для парсера '{selected_parser}'", type=['zip'], key="async_file_upload" ) if uploaded_file is not None: st.success(f"✅ Файл выбран: {uploaded_file.name}") st.info(f"📊 Размер файла: {uploaded_file.size / 1024 / 1024:.2f} MB") if st.button("🚀 Загрузить асинхронно", key="async_upload_btn", use_container_width=True): # Создаем уникальный ID задачи task_id = f"task_{int(time.time())}_{uploaded_file.name}" # Показываем сообщение о создании задачи st.success("✅ Задача загрузки создана!") st.info(f"ID задачи: `{task_id}`") st.info("📋 Перейдите на страницу 'Управление задачами' для отслеживания прогресса") # Запускаем загрузку в фоновом потоке endpoint = parser_endpoints[selected_parser] file_data = uploaded_file.read() # Создаем поток для асинхронной загрузки thread = threading.Thread( target=upload_file_async_background, args=(endpoint, file_data, uploaded_file.name, task_id) ) thread.daemon = True thread.start() # Автоматически переключаемся на страницу задач st.session_state.sidebar_tasks_clicked = True st.rerun() st.markdown("---") # Информация о поддерживаемых форматах with st.expander("ℹ️ Поддерживаемые форматы файлов"): st.markdown(""" **Поддерживаемые форматы:** - 📦 ZIP архивы с Excel файлами - 📊 Excel файлы (.xlsx, .xls) - 📋 CSV файлы (для некоторых парсеров) **Ограничения:** - Максимальный размер файла: 100 MB - Количество файлов в архиве: до 50 - Поддерживаемые кодировки: UTF-8, Windows-1251 """) # Статистика загрузок st.subheader("📈 Статистика загрузок") col1, col2, col3 = st.columns(3) with col1: st.metric("Всего загружено", "0", "0") with col2: st.metric("В обработке", "0", "0") with col3: st.metric("Завершено", "0", "0")