refactor(mikrotikApplyService): enhance file retrieval logic with improved error handling and support for large files
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m53s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m53s
This commit is contained in:
@@ -358,21 +358,74 @@ async function fetchExportViaFile(client) {
|
||||
|
||||
await client.command('export', { compact: '', file: basename });
|
||||
|
||||
const printRes = await client.command('file/print', {
|
||||
'.proplist': 'contents,.id',
|
||||
'.query': [`name=${basename}`],
|
||||
});
|
||||
const data = printRes?.data;
|
||||
const list = Array.isArray(data) ? data : (data ? [data] : []);
|
||||
// REST API: file/print — пробуем GET с query в URL (некоторые версии ожидают это)
|
||||
const qs = `?.proplist=.id,name,contents&name=${encodeURIComponent(basename)}`;
|
||||
let printRes = await client.print(`file/print${qs}`);
|
||||
let data = printRes?.data;
|
||||
let list = Array.isArray(data) ? data : (data ? [data] : []);
|
||||
|
||||
// Если по name в URL не нашли — пробуем POST с .query в body
|
||||
if (list.length === 0) {
|
||||
printRes = await client.command('file/print', {
|
||||
'.proplist': ['.id', 'name', 'contents'],
|
||||
'.query': [`name=${basename}`],
|
||||
});
|
||||
data = printRes?.data;
|
||||
list = Array.isArray(data) ? data : (data ? [data] : []);
|
||||
}
|
||||
|
||||
// Если всё ещё пусто — печатаем все файлы и ищем по имени вручную
|
||||
if (list.length === 0) {
|
||||
printRes = await client.command('file/print', {
|
||||
'.proplist': ['.id', 'name', 'contents'],
|
||||
});
|
||||
data = printRes?.data;
|
||||
list = Array.isArray(data) ? data : (data ? [data] : []);
|
||||
const found = list.find(
|
||||
(f) =>
|
||||
(f.name || '') === basename ||
|
||||
(f.name || '').endsWith('/' + basename) ||
|
||||
(f.name || '').endsWith(basename),
|
||||
);
|
||||
if (found) list = [found];
|
||||
}
|
||||
|
||||
const file = list[0];
|
||||
if (!file || file.contents == null) {
|
||||
if (!file) {
|
||||
throw new Error('Failed to read export file from MikroTik (file not found after export)');
|
||||
}
|
||||
|
||||
let config = String(file.contents || '');
|
||||
|
||||
// Для файлов >60KB API не возвращает contents в print — читаем через /file/read чанками
|
||||
if (!config && file.name) {
|
||||
const chunkSize = 32768;
|
||||
let offset = 0;
|
||||
const chunks = [];
|
||||
for (;;) {
|
||||
const readRes = await client.command('file/read', {
|
||||
file: file.name,
|
||||
offset: String(offset),
|
||||
'chunk-size': String(chunkSize),
|
||||
});
|
||||
const rd = readRes?.data;
|
||||
const chunk = Array.isArray(rd) ? (rd[0]?.data ?? rd[0]) : (rd?.data ?? rd);
|
||||
const str = typeof chunk === 'string' ? chunk : (chunk ? String(chunk) : '');
|
||||
if (!str) break;
|
||||
chunks.push(str);
|
||||
offset += str.length;
|
||||
if (str.length < chunkSize) break;
|
||||
}
|
||||
config = chunks.join('');
|
||||
}
|
||||
|
||||
if (!config) {
|
||||
try {
|
||||
const id = file?.['.id'];
|
||||
const id = file['.id'];
|
||||
if (id) await client.remove(`file/${id}`);
|
||||
} catch (_) {}
|
||||
throw new Error('Failed to read export file from MikroTik');
|
||||
throw new Error('Failed to read export file from MikroTik (file/print and file/read returned no contents)');
|
||||
}
|
||||
const config = String(file.contents || '');
|
||||
|
||||
try {
|
||||
const id = file['.id'];
|
||||
|
||||
Reference in New Issue
Block a user