Files
loadtest/site/templates/index.html
T

212 lines
9.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<!-- LoadTest - страница проверки загрузки файлов. -->
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoadTest - проверка загрузки файлов</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="wrap">
<h1>LoadTest - проверка загрузки файлов</h1>
<p class="hint">
Выберите ОДИН файл (в т.ч. большой) и нажмите «Загрузить».
Файл читается в память Flask (на диск не пишется). Результат: файл дошёл или нет + статистика.
</p>
<!-- Панель выбора файла и кнопка загрузки -->
<div class="panel">
<label for="file">Файл:</label>
<input type="file" id="file">
<button id="btn" onclick="startUpload()">Загрузить</button>
</div>
<!-- Индикатор прогресса: полоса, % и таймер -->
<div class="progress-wrap" id="progressWrap" style="display:none">
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="progress-info">
<span id="progressPct">0%</span>
<span id="progressTimer">0с</span>
<span id="progressSpeed"></span>
</div>
</div>
<!-- Итоговый статус: УСПЕХ / ОШИБКА -->
<div id="status"></div>
<!-- Максимум статистики (клиент + сервер) -->
<pre id="result"></pre>
</div>
<script>
// ---------- Загрузка одного файла через XMLHttpRequest ----------
// XHR даёт реальный прогресс отправки (fetch - не даёт), поэтому берём XHR.
function startUpload() {
var input = document.getElementById('file');
var file = input.files[0];
// Сброс старых данных.
var result = document.getElementById('result');
var status = document.getElementById('status');
var wrap = document.getElementById('progressWrap');
result.textContent = '';
status.textContent = '';
if (!file) {
status.textContent = 'ОШИБКА: выберите файл';
status.className = 'status error';
return;
}
// ---- Статистика клиента ----
var startMs = Date.now(); // время начала загрузки (клиент)
var fileSize = file.size; // размер файла (байт)
var fileSizeMB = fileSize / (1024 * 1024);
var startLocal = new Date().toLocaleTimeString();
// ---- Прогресс: полоса + % ----
wrap.style.display = 'block';
var fill = document.getElementById('progressFill');
var pctEl = document.getElementById('progressPct');
var timerEl = document.getElementById('progressTimer');
var speedEl = document.getElementById('progressSpeed');
fill.style.width = '0%';
pctEl.textContent = '0%';
timerEl.textContent = '0с';
speedEl.textContent = '';
// Таймер (второстепенно): обновляем прошедшие секунды каждую 1с.
var timer = setInterval(function () {
var sec = Math.floor((Date.now() - startMs) / 1000);
timerEl.textContent = sec + 'с';
}, 1000);
// ---- Формируем multipart-запрос ----
var fd = new FormData();
fd.append('file', file, file.name); // поле должно называться 'file' (см. app.py)
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
// Таймаут 10 минут - большие файлы могут ехать долго.
xhr.timeout = 600000;
// Реальный прогресс отправки тела запроса (loaded - отправлено байт).
xhr.upload.onprogress = function (e) {
if (!e.lengthComputable) {
pctEl.textContent = '?%';
return;
}
var pct = Math.round(e.loaded / e.total * 100);
fill.style.width = pct + '%';
pctEl.textContent = pct + '%';
// Мгновенная средняя скорость клиента.
var sec = (Date.now() - startMs) / 1000;
if (sec > 0) {
var mbps = (e.loaded / (1024 * 1024)) / sec;
speedEl.textContent = mbps.toFixed(2) + ' МБ/с';
}
};
// ---- Ответ сервера получен ----
xhr.onload = function () {
clearInterval(timer);
var sec = ((Date.now() - startMs) / 1000).toFixed(2);
var httpStatus = xhr.status;
var ok = xhr.status >= 200 && xhr.status < 300;
// Сервер может ответить и НЕ-JSON (413, HTML ошибки прокси) - показываем текст.
var data = null;
try { data = JSON.parse(xhr.responseText); } catch (e) { data = null; }
if (ok && data && data.ok) {
// УСПЕХ - файл дошёл до бэкенда.
status.textContent = '✅ ФАЙЛ ЗАГРУЖЕН';
status.className = 'status ok';
renderStats(file, fileSize, fileSizeMB, startLocal, sec, httpStatus, data);
} else {
// ОШИБКА - показываем статус, текст сервера и клиентскую статистику.
status.textContent = '❌ ФАЙЛ НЕ ЗАГРУЖЕН (HTTP ' + httpStatus + ')';
status.className = 'status error';
var errBody = data && data.error ? 'ошибка: ' + data.error : xhr.responseText;
result.textContent =
'HTTP статус: ' + httpStatus + '\n' +
'Ответ сервера: ' + (errBody || '(пусто)') + '\n' +
clientStats(file, fileSize, fileSizeMB, startLocal, sec);
}
};
// ---- Сеть: соединение оборвано, нет ответа ----
xhr.onerror = function () {
clearInterval(timer);
var sec = ((Date.now() - startMs) / 1000).toFixed(2);
status.textContent = '❌ СЕТЕВАЯ ОШИБКА - ответа нет';
status.className = 'status error';
result.textContent = clientStats(file, fileSize, fileSizeMB, startLocal, sec) +
'\n(соединение прервано, прокси/платформа не ответила)';
};
// ---- Таймаут ----
xhr.ontimeout = function () {
clearInterval(timer);
var sec = ((Date.now() - startMs) / 1000).toFixed(2);
status.textContent = '❌ ТАЙМАУТ (10 мин) - файл не загружен';
status.className = 'status error';
result.textContent = clientStats(file, fileSize, fileSizeMB, startLocal, sec);
};
xhr.send(fd);
}
// ---- Клиентская статистика (общая для всех исходов) ----
function clientStats(file, size, sizeMB, startLocal, sec) {
var avg = sec > 0 ? (size / (1024 * 1024) / sec).toFixed(2) : '0';
return '-- КЛИЕНТ --\n' +
'Файл: ' + file.name + '\n' +
'Размер: ' + size + ' байт (' + sizeMB.toFixed(3) + ' МБ)\n' +
'Начало: ' + startLocal + '\n' +
'Длительность: ' + sec + ' с\n' +
'Средняя скорость: ' + avg + ' МБ/с\n';
}
// ---- Полная статистика при успехе: клиент + сервер ----
function renderStats(file, size, sizeMB, startLocal, sec, httpStatus, data) {
var f = data.file;
var s = data.server;
var m = data.meta;
var avg = sec > 0 ? (size / (1024 * 1024) / sec).toFixed(2) : '0';
var out = '';
out += '-- КЛИЕНТ --\n' +
'Файл: ' + file.name + '\n' +
'Размер: ' + size + ' байт (' + sizeMB.toFixed(3) + ' МБ)\n' +
'Начало: ' + startLocal + '\n' +
'Длительность: ' + sec + ' с\n' +
'Средняя скорость (клиент): ' + avg + ' МБ/с\n' +
'HTTP статус: ' + httpStatus + '\n\n';
out += '-- СЕРВЕР (что реально дошло) --\n' +
'Имя файла: ' + f.name + '\n' +
'MIME: ' + f.mime + '\n' +
'Принято байт: ' + f.size_bytes + ' (' + f.size_mb + ' МБ)\n' +
'Чтение в память: ' + s.read_ms + ' мс\n' +
'Обработка всего: ' + s.total_ms + ' мс\n' +
'Скорость (сервер): ' + s.speed_mb_s + ' МБ/с\n' +
'MD5 принятых байт: ' + data.md5 + '\n\n';
out += '-- ЗАПРОС --\n' +
'Время сервера: ' + m.server_start + '\n' +
'Remote addr: ' + m.remote_addr + '\n' +
'Content-Length (заголовок): ' + m.content_length_header + '\n' +
'Content-Type (заголовок): ' + m.content_type_header + '\n' +
'User-Agent: ' + m.user_agent;
result.textContent = out;
}
</script>
</body>
</html>