Напрямую использовать form-data пока нет возможности. Но form-data - это всего-лишь определенная структура тела запроса и эту структуру можно реализовать на "низком уровне". Вот пример:
// Loginom JS node: POST multipart/form-data с xlsx (поле "file")
import { fetch, Headers } from "builtIn/Fetch";
import * as fs from "builtIn/FS";
// UTF-8 → bytes
function strToUtf8Bytes(str) {
let bytes = [];
for (let i = 0; i < str.length; i++) {
let c = str.charCodeAt(i);
if (c < 0x80) bytes.push(c);
else if (c < 0x800) { bytes.push(0xC0 | (c>>6), 0x80 | (c & 0x3F)); }
else if (c >= 0xD800 && c <= 0xDBFF) {
i++; let n = str.charCodeAt(i);
let cp = ((c - 0xD800)<<10) + (n - 0xDC00) + 0x10000;
bytes.push(0xF0 | (cp>>18), 0x80 | ((cp>>12)&0x3F), 0x80 | ((cp>>6)&0x3F), 0x80 | (cp&0x3F));
} else { bytes.push(0xE0 | (c>>12), 0x80 | ((c>>6)&0x3F), 0x80 | (c&0x3F)); }
}
return new Uint8Array(bytes);
}
function concatBytes(chunks) {
let total = 0, i;
for (i=0;i<chunks.length;i++) total += chunks[i].length;
let out = new Uint8Array(total), off = 0;
for (i=0;i<chunks.length;i++) { out.set(chunks[i], off); off += chunks[i].length; }
return out;
}
function strBytes(s){ return strToUtf8Bytes(s); }
// Собрать multipart с ОДНИМ файлом (поле "file")
function buildMultipartFilePart(fieldName, filename, contentType, fileBytes) {
let boundary = "----LoginomBoundary" + Math.floor(Math.random()*1e9);
let CRLF = "\r\n";
let chunks = [];
// filename* по RFC 5987
let fnStar = "UTF-8''" + encodeURIComponent(filename);
let disp =
'Content-Disposition: form-data; name="' + fieldName + '"; ' +
'filename="' + filename.replace(/"/g, '\\"') + '"; ' +
'filename*=' + fnStar + CRLF;
chunks.push(strBytes("--"+boundary+CRLF));
chunks.push(strBytes(disp));
chunks.push(strBytes("Content-Type: " + (contentType || "application/octet-stream") + CRLF + CRLF));
chunks.push(fileBytes instanceof Uint8Array ? fileBytes : new Uint8Array(fileBytes));
chunks.push(strBytes(CRLF));
chunks.push(strBytes("--"+boundary+"--"+CRLF));
return { body: concatBytes(chunks), boundary: boundary };
}
(async function () {
try {
// Путь к XLSX в доступной Loginom-папке
let path = "upload/Лист Microsoft Excel.xlsx"; // <-- поправить при необходимости
let filename = "Лист Microsoft Excel.xlsx";
let url = "https://httpbin.org/post?test=loginom";
let fileBytes = new Uint8Array(fs.readFileSync(path)); // делаем бинарь
let mp = buildMultipartFilePart(
"file",
filename,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
fileBytes
);
let headers = new Headers({
"Content-Type": "multipart/form-data; boundary=" + mp.boundary
// Content-Length не задаём — fetch его считает сам
});
let resp = await fetch(url, { method: "POST", headers: headers, body: mp.body });
let text = await resp.text();
console.log("Status:", resp.status, "OK?", resp.ok);
console.log(text);
} catch (e) {
console.error("Upload error:", e);
}
})();
Поправьте:
let path = "upload/Лист Microsoft Excel.xlsx"; // <-- поправить при необходимости
let filename = "Лист Microsoft Excel.xlsx";
let url = "https://httpbin.org/post?test=loginom";
на свои параметры или лучше импортируйте их из входных переменных узла JS