diff --git a/site/templates/upload.html b/site/templates/upload.html
index dd02aef..131621d 100644
--- a/site/templates/upload.html
+++ b/site/templates/upload.html
@@ -59,7 +59,7 @@
 }})
-
Сверка договоров v1.41
+
Сверка договоров v1.42
@@ -155,35 +155,57 @@
window.removeFile = removeFile;
- // ── Загрузка base64 (JSON) ──────────────────────────────────
+ // ── Чанковая загрузка 30KB ─────────────────────────────────
- function uploadFileJSON(file, cid, onProgress) {
+ function uploadFileChunked(file, cid, onProgress) {
return new Promise(function(resolve, reject) {
var reader = new FileReader();
reader.onload = function() {
var b64 = reader.result.split(',')[1];
- var xhr = new XMLHttpRequest();
- xhr.open('POST', '/upload');
- xhr.setRequestHeader('Content-Type', 'application/json');
- xhr.timeout = 30000;
- xhr.upload.onprogress = function(e) {
- if (e.lengthComputable && onProgress) onProgress(Math.round(e.loaded / e.total * 100));
- };
- xhr.onload = function() {
- if (xhr.status === 200) {
- try { resolve(JSON.parse(xhr.responseText)); }
- catch(e) { reject(new Error('Bad JSON')); }
- } else { reject(new Error('HTTP ' + xhr.status)); }
- };
- xhr.onerror = function() { reject(new Error('Сеть')); };
- xhr.ontimeout = function() { reject(new Error('Таймаут')); };
- xhr.send(JSON.stringify({filename: file.name, data: b64, cid: cid || null}));
+ var CHUNK = 30 * 1024;
+ var totalChunks = Math.ceil(b64.length / CHUNK);
+ var uploadId = file.name + '_' + Date.now() + '_' + Math.random().toString(36).substr(2, 6);
+ var done = 0;
+
+ function sendChunk(i) {
+ if (i >= totalChunks) { resolve({contract_id: cid}); return; }
+ var piece = b64.substring(i * CHUNK, (i + 1) * CHUNK);
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', '/chunk_json');
+ xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.timeout = 15000;
+ xhr.onload = function() {
+ if (xhr.status === 200) {
+ try {
+ var resp = JSON.parse(xhr.responseText);
+ if (resp.error) { reject(new Error(resp.error)); return; }
+ if (resp.contract_id) cid = resp.contract_id;
+ done++;
+ if (onProgress) onProgress(Math.round(done / totalChunks * 100));
+ setTimeout(function() { sendChunk(i + 1); }, 100);
+ } catch(e) { reject(new Error('Bad JSON')); }
+ } else { reject(new Error('HTTP ' + xhr.status)); }
+ };
+ xhr.onerror = function() { reject(new Error('Сеть')); };
+ xhr.ontimeout = function() { reject(new Error('Таймаут')); };
+ xhr.send(JSON.stringify({
+ upload_id: uploadId,
+ filename: file.name,
+ chunk_index: i,
+ total_chunks: totalChunks,
+ data: piece,
+ cid: cid || null
+ }));
+ }
+ sendChunk(0);
};
reader.onerror = function() { reject(new Error('Read error')); };
reader.readAsDataURL(file);
});
}
+ // ── Старая загрузка (одним POST) ─────────────────────────────
+
// ── Выбор файла → сразу загрузка ────────────────────────────
fileInput.addEventListener('change', async function() {
@@ -205,7 +227,7 @@
var startTime = Date.now();
try {
- var resp = await uploadFileJSON(f, contractId, function(pct) {
+ var resp = await uploadFileChunked(f, contractId, function(pct) {
fileQueue[rowIdx].status = '↑ ' + pct + '%';
renderTable();
});