# Upload module (v0.2.0) Переиспользуемый модуль загрузки, состоящий из двух независимых слоёв: 1. **Слой 1 (`upload/frontend/`)** — File Picker: - IIFE: `FilePicker.initFilePicker(config)`; - ESM: `import { initFilePicker } from './file-picker.esm.js'` (или из `upload/frontend/index.js`). - Получение выбранных файлов: `picker.getFiles()` возвращает плоский массив `{ path, name, size, file }`. - Поддерживает выбор файлов, папок, клиентскую распаковку ZIP (fflate) и проверку лимитов. 2. **Слой 2 (`upload/frontend/upload/` + `upload/backend/`)** — Пофайловый транзит в RAM сессии: - Фронтенд: `uploadViaVM(files, options)` или `FilePicker.uploadViaVM(files, options)`: - Пофайловый стриминг: для каждого файла выполняется `PUT` в буфер на ВМ, немедленный `POST /api/upload_refs` в бэкенд, и после подтверждения приёма буфер на ВМ очищается. - Поддержка `AbortSignal` для отмены загрузки на любом этапе. - Бэкенд: `create_upload_refs_blueprint(cfg)`: - Приём ссылок через исходящий потоковый `GET` в память RAM. - SSRF-валидация префикса буфера (`vmUploadPrefix`). - Защита от path traversal (`safe_name`). - Хранилище сессий в оперативной памяти (`upload/backend/session`). - Никакой записи на диск. ## Интеграция в сторонний проект 1. Скопировать каталог `upload/` в проект. 2. Во Flask подключить Blueprint: ```python from upload.backend.upload_refs import create_upload_refs_blueprint app.register_blueprint(create_upload_refs_blueprint({"vmUploadPrefix": "..."})) ``` 3. На фронтенде подключить `file-picker.iife.js` или импортировать ESM. 4. Вызвать `initFilePicker`, а при отправке вызвать `uploadViaVM(picker.getFiles(), options)`.