v0.0.6: прогресс загрузки в строке (XMLHttpRequest onprogress)
Deploy drhider / validate (push) Waiting to run
Deploy drhider / validate (push) Waiting to run
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@ if _sys_path_root not in sys.path:
|
|||||||
sys.path.insert(0, _sys_path_root)
|
sys.path.insert(0, _sys_path_root)
|
||||||
|
|
||||||
# Версия приложения (меняется при изменениях)
|
# Версия приложения (меняется при изменениях)
|
||||||
VERSION = "0.0.5"
|
VERSION = "0.0.6"
|
||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
|
|||||||
@@ -156,21 +156,44 @@ async function uploadFiles() {
|
|||||||
db.classList.remove('show');
|
db.classList.remove('show');
|
||||||
const total = sf.length;
|
const total = sf.length;
|
||||||
|
|
||||||
// Фаза 1: загрузка
|
// Фаза 1: загрузка (XMLHttpRequest — прогресс в строке)
|
||||||
for (let i = 0; i < total; i++) {
|
for (let i = 0; i < total; i++) {
|
||||||
const f = sf[i], n = i + 1;
|
const f = sf[i], n = i + 1;
|
||||||
ss(i, '<span style="color:#2563eb">⏳ загрузка</span>');
|
|
||||||
st.className = 'status progress';
|
st.className = 'status progress';
|
||||||
st.textContent = 'Загрузка ' + n + '/' + total + ': ' + f.name;
|
st.textContent = 'Загрузка ' + n + '/' + total + ': ' + f.name;
|
||||||
|
try {
|
||||||
|
const t0 = performance.now();
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('POST', '/api/upload');
|
||||||
|
xhr.upload.onprogress = function(e) {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const pct = Math.round(e.loaded / e.total * 100);
|
||||||
|
ss(i, '<span style="color:#2563eb">⏳ ' + pct + '%</span>');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
const data = JSON.parse(xhr.responseText);
|
||||||
|
if (data.ok) {
|
||||||
|
const elapsed = (performance.now() - t0) / 1000;
|
||||||
|
const speed = f.size / elapsed;
|
||||||
|
ss(i, '<span style="color:#22c55e">✓ ' + fs(speed) + '/s</span>');
|
||||||
|
currentSid = data.session;
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(new Error(data.error));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject(new Error('HTTP ' + xhr.status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function() { reject(new Error('Сеть')); };
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('files', f, f.name);
|
fd.append('files', f, f.name);
|
||||||
if (currentSid) fd.append('session', currentSid);
|
if (currentSid) fd.append('session', currentSid);
|
||||||
try {
|
xhr.send(fd);
|
||||||
const resp = await fetch('/api/upload', { method: 'POST', body: fd });
|
});
|
||||||
const data = await resp.json();
|
|
||||||
if (!data.ok) throw new Error(data.error);
|
|
||||||
currentSid = data.session;
|
|
||||||
ss(i, '<span style="color:#22c55e">✓ загружен</span>');
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ss(i, '<span style="color:#ef4444">✗</span>');
|
ss(i, '<span style="color:#ef4444">✗</span>');
|
||||||
st.className = 'status error';
|
st.className = 'status error';
|
||||||
|
|||||||
Reference in New Issue
Block a user