Из серверной части node.js мне нужно отправить HTTP-сообщение на конечную точку REST. Конечной точке требуются некоторые параметры, которые она ожидает найти в HTTP-сообщении. Некоторые параметры достаточно просты: в качестве аргумента требуется число или строка. Но одним из параметров является «загружаемое необработанное содержимое двоичного файла», и это меня озадачило. Насколько я понимаю, параметры нужно собрать в строку, чтобы поместить в тело HTTP-запроса; Как добавить необработанные двоичные данные в строку? Очевидно, что для того, чтобы он был в строке, это не могут быть необработанные двоичные данные; его нужно закодировать в символы.
Рассматриваемой конечной точкой является API загрузки мультимедиа в Твиттер. Параметр «необработанные двоичные данные» называется media
. Ниже приведен неполный фрагмент кода, показывающий основную суть того, что я пробовал. В частности, строка, в которой я строю строку requestBody
. Я не думаю, что это правильно, потому что конечная точка возвращает сообщение «неверный запрос».
var https = require("https");
var base64ImageData = /* (some base 64 string here) */;
var options = {
host: "api.twitter.com",
path: "/1.1/media/upload.json",
method: "POST",
headers: {
"Content-Type": "multipart/form-data"
}
};
var request = https.request(options, function(response) {});
var requestBody = "media_id=18283918294&media = " + Buffer.from(base64ImageData, "base64").toString("binary");
request.write(requestBody);
request.end();
Также стоит отметить, что сами Twitter отмечают следующее крайне запутанное заявление:
«При публикации изображений, закодированных в base64, обязательно установите «Content-Transfer-Encoding: base64» в графической части сообщения».
Источник: https://developer.twitter.com/en/docs/media/upload-media/uploading-media/media-best-practices
Это может быть частью ответа на мой вопрос, но я не понимаю: Как применить разные заголовки к разным частям HTTP-сообщения? Поскольку, очевидно, данные изображения должны иметь заголовок Content-Transfer-Encoding «base64», в то время как остальная часть сообщения HTTP не ...
How do I apply different headers to different parts of the HTTP message?
В этом суть типа контента multipart/form-data
. Сообщение, состоящее из нескольких частей, выглядит так:
Content-Type: multipart/form-data; boundary=---foo---
---foo---
Content-Disposition: form-data; name = "datafile1"; filename = "r.gif"
Content-Transfer-Encoding: base64
Content-Type: image/gif
// data goes here
---foo---
Content-Disposition: form-data; name = "datafile2"; filename = "g.png"
Content-Transfer-Encoding: base64
Content-Type: image/png
// another file's data goes here
---foo---
Вы, вероятно, не хотите собирать все это вместе. Существует множество хороших библиотек для составления сложных POST-запросов. Например: https://www.npmjs.com/package/form-data
@CircuitScholar — это параметры запроса, они не являются частью тела запроса. Когда этот формат используется в теле запроса, тип контента — application/x-www-form-urlencoded
.
Документы @CircuitScholar в Твиттере всегда были немного дерьмовыми. Перестаньте предполагать последствия — есть вероятность, что если что-то странное/бессмысленное в их документах, это просто Твиттер — это Твиттер. Вы не отправляете большие многомегабайтные данные файла в качестве параметра URL.
(Примечание: см. пошаговое руководство на developer.twitter.com/ru/docs/media/upload-media/… для фрагментированных загрузок и используйте этот бит: «Чтобы увидеть полные заголовки запросов и ответов при использовании twurl, используйте параметр -t для включения режима трассировки». )
Спасибо, но меня по-прежнему сбивает с толку конкретный случай с Твиттером. Их документация строго подразумевает, что данные файла просто должны быть предоставлены в виде формата параметра URL. developer.twitter.com/en/docs/media/upload-media/api-reference/…. См. предоставленный пример:
command=APPEND&media_id=123&segment_index=2&media_data=123
Можете ли вы предположить, почему это может быть так? Также, чтобы было ясно, в вашем примере сообщения, состоящего из нескольких частей, все это идет в теле? Входит лиboundary=--foo--
в заголовок Content-Type?