feat: base64-режим загрузки (обход DDOS-Guard), v1.0.3
Deploy loadtest / validate (push) Waiting to run
Deploy loadtest / validate (push) Waiting to run
This commit is contained in:
+12
-1
@@ -1,9 +1,10 @@
|
|||||||
import time
|
import time
|
||||||
|
import base64
|
||||||
from flask import Flask, render_template, request
|
from flask import Flask, render_template, request
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
VERSION = '1.0.2'
|
VERSION = '1.0.3'
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@@ -20,6 +21,16 @@ def health():
|
|||||||
def upload():
|
def upload():
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
total = 0
|
total = 0
|
||||||
|
# base64-режим: клиент отправляет поле "data"
|
||||||
|
data = request.form.get('data', '')
|
||||||
|
if data:
|
||||||
|
# убрать префикс data:...;base64,
|
||||||
|
if ',' in data:
|
||||||
|
data = data.split(',', 1)[1]
|
||||||
|
raw = base64.b64decode(data)
|
||||||
|
elapsed = round((time.time() - t0) * 1000)
|
||||||
|
return {'ok': True, 'bytes': len(raw), 'elapsed_ms': elapsed}
|
||||||
|
# старый режим: файл напрямую (может не работать через DDOS-Guard)
|
||||||
for f in request.files.values():
|
for f in request.files.values():
|
||||||
while True:
|
while True:
|
||||||
chunk = f.read(8192)
|
chunk = f.read(8192)
|
||||||
|
|||||||
+48
-32
@@ -180,48 +180,64 @@ async function uploadAll() {
|
|||||||
fileSummary.textContent = summary;
|
fileSummary.textContent = summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** uploadOne(fileEntry, idx) — XHR одного файла, возвращает {bytes, elapsed_ms} */
|
/** uploadOne(fileEntry, idx) — читает файл в base64, отправляет как поле формы */
|
||||||
function uploadOne(f, idx) {
|
function uploadOne(f, idx) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var xhr = new XMLHttpRequest();
|
// Шаг 1: прочитать файл в base64
|
||||||
var fd = new FormData();
|
f.status = 'uploading';
|
||||||
fd.append('file', f.file, f.name);
|
f.progress = 0;
|
||||||
|
renderTable();
|
||||||
|
|
||||||
var t0 = Date.now();
|
var reader = new FileReader();
|
||||||
|
reader.onload = function () {
|
||||||
|
// base64-строка готова, теперь отправляем
|
||||||
|
var t0 = Date.now();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
var fd = new FormData();
|
||||||
|
fd.append('data', reader.result);
|
||||||
|
fd.append('name', f.name);
|
||||||
|
fd.append('orig_size', f.size);
|
||||||
|
|
||||||
xhr.open('POST', '/upload');
|
xhr.open('POST', '/upload');
|
||||||
|
|
||||||
xhr.upload.onprogress = function (e) {
|
xhr.upload.onprogress = function (e) {
|
||||||
if (e.lengthComputable) {
|
if (e.lengthComputable) {
|
||||||
f.progress = Math.round(e.loaded / e.total * 100);
|
f.progress = Math.round(e.loaded / e.total * 100);
|
||||||
renderTable();
|
renderTable();
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.onload = function () {
|
|
||||||
try {
|
|
||||||
var r = JSON.parse(xhr.responseText);
|
|
||||||
if (r.ok) {
|
|
||||||
resolve({ bytes: r.bytes, elapsed_ms: r.elapsed_ms });
|
|
||||||
} else {
|
|
||||||
reject(new Error(r.error || 'Ошибка сервера'));
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
};
|
||||||
reject(new Error('Некорректный ответ'));
|
|
||||||
}
|
xhr.onload = function () {
|
||||||
|
try {
|
||||||
|
var r = JSON.parse(xhr.responseText);
|
||||||
|
if (r.ok) {
|
||||||
|
resolve({ bytes: r.bytes, elapsed_ms: r.elapsed_ms });
|
||||||
|
} else {
|
||||||
|
reject(new Error(r.error || 'Ошибка сервера'));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reject(new Error('Некорректный ответ'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function () {
|
||||||
|
var elapsed = Date.now() - t0;
|
||||||
|
reject(new Error('Сеть (' + (elapsed / 1000).toFixed(0) + 'с)'));
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
reject(new Error('Таймаут (' + (xhr.timeout / 1000) + 'с)'));
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.timeout = 600000; // 10 минут (base64 +33%)
|
||||||
|
xhr.send(fd);
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = function () {
|
reader.onerror = function () {
|
||||||
var elapsed = Date.now() - t0;
|
reject(new Error('Ошибка чтения файла'));
|
||||||
reject(new Error('Сеть (' + (elapsed / 1000).toFixed(0) + 'с)'));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
reader.readAsDataURL(f.file);
|
||||||
reject(new Error('Таймаут (' + (xhr.timeout / 1000) + 'с)'));
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.timeout = 300000; // 5 минут на файл
|
|
||||||
xhr.send(fd);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user