diff --git a/deploy/files.js b/deploy/files.js index 7da51bd..2c63abc 100644 --- a/deploy/files.js +++ b/deploy/files.js @@ -294,25 +294,21 @@ function applyParseResult(entry, parsed, elapsed) { } /** - * addZipFile(file) — Async-action: обработка ZIP-файла (Фаза 1). + * addZipFile(file) — Async-action: обработка ZIP-файла (Фаза 1, упрощена). * - * 1. Показывает временную строку «⏳ распаковка...» - * 2. Отправляет ZIP на бэкенд (UNZIP_URL) - * 3. Убирает временную строку - * 4. Добавляет файлы из архива в state.files, пропуская дубликаты - * 5. Для каждого: applyParseResult (результат парсинга от бэкенда) + * 1. Отправляет ZIP на бэкенд (только распаковка, без БД/парсинга) + * 2. Для каждого файла из архива: base64 → Blob → File → addRegularFile() * - * Мутирует state.files, вызывает render(state) после каждого изменения. + * addRegularFile делает ВСЁ: upload, parse, дубликаты, статусы, render. + * Никакого дублирования логики — единый путь для обычных и ZIP-файлов. */ async function addZipFile(file) { - // Показать временную строку для ZIP var zipEntry = { name: file.name, lastModified: file.lastModified, size: file.size, status: { kind: 'unzipping' } }; state.files.push(zipEntry); var zipIdx = state.files.length - 1; render(state); try { - // Отправить ZIP на бэкенд (multipart — бэкенд ищет boundary + PK magic) var zipResp = await new Promise(function(resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open('POST', UNZIP_URL); @@ -331,42 +327,21 @@ async function addZipFile(file) { state.files.splice(zipIdx, 1); render(state); - // Добавить файлы из архива (дубликаты перезаписываются) + // Каждый файл из архива — через addRegularFile (единый путь) for (var zi = 0; zi < zipResp.files.length; zi++) { var zf = zipResp.files[zi]; - if (zf.error) continue; // файл с ошибкой — пропускаем + if (zf.error) continue; - var zEntry = { - name: zf.filename, size: zf.size, - doc_id: zf.doc_id, uploaded: true, - status: { kind: 'parsing' } - }; + // base64 → Blob → File + var byteStr = atob(zf.data_b64); + var bytes = new Uint8Array(byteStr.length); + for (var b = 0; b < byteStr.length; b++) bytes[b] = byteStr.charCodeAt(b); + var mime = {docx:'application/vnd.openxmlformats-officedocument.wordprocessingml.document',doc:'application/msword',pdf:'application/pdf'}[zf.ext] || 'application/octet-stream'; + var extractedFile = new File([bytes], zf.filename, { type: mime, lastModified: Date.now() }); - // Проверить дубликат по имени - var dup = -1; - for (var dj = 0; dj < state.files.length; dj++) { - if (state.files[dj].name === zf.filename) { dup = dj; break; } - } - - if (dup >= 0) { - // Заменить существующий (как addRegularFile — перезапись) - state.files[dup] = zEntry; - } else { - state.files.push(zEntry); - dup = state.files.length - 1; - } - - // Если это первый файл — запомнить contract_id - if (!state.contractId && zf.contract_id) state.contractId = zf.contract_id; - render(state); - - // Применить результат парсинга от бэкенда (clean function) - applyParseResult(state.files[dup], zf.parsed); - render(state); + await addRegularFile(extractedFile); } } catch(ze) { - // Ошибка распаковки — показать в строке ZIP - console.error('addZipFile error:', ze, 'UNZIP_URL=', UNZIP_URL); state.files[zipIdx].status = { kind: 'error', text: 'ZIP: ' + ze.message }; render(state); } @@ -393,6 +368,10 @@ async function addRegularFile(file) { } var rowIdx; if (existingIdx >= 0) { + // Файл с таким именем уже есть — спросить пользователя + if (!confirm('Файл «' + file.name + '» уже есть в списке.\n\nOK — перезаписать\nОтмена — пропустить')) { + return; // пользователь выбрал «пропустить» + } state.files[existingIdx] = entry; rowIdx = existingIdx; } else { diff --git a/deploy/services/unzip.py b/deploy/services/unzip.py index 3fbcb1f..b4b0b67 100644 --- a/deploy/services/unzip.py +++ b/deploy/services/unzip.py @@ -1,20 +1,17 @@ -"""Unzip service — extract files from ZIP archive.""" -import zipfile, io, base64, json +"""Unzip service — extract files from ZIP archive (no DB, no parse).""" +import zipfile, io, base64 def handle_unzip(rfile, content_length): - """Parse ZIP upload, return list of extracted files.""" + """Parse ZIP upload, return list of extracted files as base64.""" body = rfile.read(content_length) # Find file data in raw multipart - # Simple approach: find ZIP bytes after header idx = body.find(b"\r\n\r\n") if idx < 0: return {"ok": False, "error": "invalid multipart"} - # Find first boundary end raw = body[idx + 4:] - # Find the actual ZIP data (after Content-Disposition etc) zip_start = raw.find(b"PK\x03\x04") if zip_start < 0: return {"ok": False, "error": "not a ZIP file"} diff --git a/index.cfm b/index.cfm index 479ad70..dd4f265 100644 --- a/index.cfm +++ b/index.cfm @@ -94,7 +94,7 @@