Передать файл через Post-запрос

0 голосов
Андрей АВ в категории Как сделать...
Возможно ли отправить Post запрос и передать файл?

Ответ: 1 шт.

0 голосов
Илья Бастраков
Здравствуйте!
Прошу написать подробнее кейс использования и откуда должен браться файл.
Андрей АВ
Обрабатываем данные и хотим передать их в запросе в виде файла xlsx, предполагаю надо
1) сохранить файл на сервере

2) через JS получить этот файл и выполнить fetch, передав в formData

Надо отправить post запрос с параметрами в заголовке и передать файл.
Илья Бастраков
Данный функционал отправить файл xlsx через POST-запрос в Loginom не существует на данный момент.

Как обходное решение Ваш порядок действий является верным.

Из-за недостаточной информации тяжело понять, что Вы планируете сделать.
Андрей АВ

прикладываю скрин из Postman как в нем выполняю требуемый запрос + базовая аутентификация.

Возможно ли в узле JS сделать отправку файла? Файл например лежит в той же папке где и пакет Loginom.

vitaliy.tatarskih

Напрямую использовать 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

Андрей АВ
Проще получилось сделать в узле Py

filedata = {'file': open(path, 'rb')}

response = requests.post(

                api_url,

                params={'param1': param1,'param2': param2},

                stream=True,

                files=filedata,

                auth=HTTPBasicAuth(username, password),

                verify=False

            )
...