كيفية تحميل الصور عبر API باستخدام Node.js؟

تم طرح هذا السؤال عدة مرات، لكن لم تنجح أي من الحلول حتى الآن بالنسبة لي.

أنا أستخدم Node.js لرفع الصور لمنشور عبر واجهة برمجة التطبيقات (API).

يمكنني إنشاء المنشورات دون أي مشكلة، لكن الصور لا يتم رفعها.

أقوم بتحويل الصورة (ملف PNG) إلى سلسلة ثنائية.

ثم أقوم بإرسال طلب application/json مع بيانات الاعتماد الخاصة بواجهة برمجة التطبيقات في الرؤوس، مع حمولة مثل هذا:

{
   type: "composer",
   synchronous: true,
   file: `${binary_string}`
}

لقد جربت كلاً من file كاسم الحقل للملف كما تقول وثائق الواجهة، وكذلك files[] كما اقترح موضوع آخر في المنتدى.

باستخدام file، أحصل على خطأ 422 مع الرسالة:

undefined method `tempfile' for #<String:0x00007fdfeba2b1d8>

باستخدام files[]، أحصل على خطأ 422 مع رسالة “Unprocessable Entity”.

بالإضافة إلى application/json كما تنص الوثائق، جربت أيضًا multipart/form-data كما تفعل واجهة المستخدم على الويب وكما فعل هذا المشارك.

في حالة إرسال طلب form-data، قمت بذلك على النحو التالي:

 const form = new FormData();
 form.append("type", "composer");
 form.append("synchronous", "true");
 form.append("files[]", this.stringToBinary(file.data!), {
      contentType: file.mimetype,
 });

http.post("/uploads.json", form.getBuffer(), {
  headers: form.getHeaders(),
 }) // creds get added

مع هذا الإرسال، سواء استخدمت file أو files[]، أحصل على خطأ 422 مع الرسالة:

undefined method `tempfile' for #<String:0x00007fdfeba2b1d8>

هل يمكن لأي شخص المساعدة؟

تمكنت من جعل هذا يعمل بهذه الطريقة:

import Axios from "axios";
import FormData from "form-data";
import fs from "fs";
const http = Axios.create({
  baseURL: "https://forum.zeebe.io",
  headers: {
    "Api-Key":
      "...",
    "Api-Username": "...",
    "Content-Type": "application/json",
    Accept: "application/json",
  },
});
http.interceptors.request.use((config) => {
  if (config.data instanceof FormData) {
    Object.assign(config.headers, config.data.getHeaders());
  }
  return config;
});

const filename = "/Users/sitapati/Desktop/process.png";
const file = fs.readFileSync(filename);
const form = new FormData();
form.append("files[]", file, {
  filename,
});

http
  .post("/uploads.json", form, {
    params: {
      type: "composer",
      synchronous: true,
    },
  })
  .then(({ data }) => {
    console.info("استجابة من Discourse", JSON.stringify(data, null, 2));
    return {
      url: data.url,
    };
  })
  .catch((e) => {
    console.error(
      "خطأ في تحميل الملف إلى Discourse",
      JSON.stringify(e, null, 2)
    );
    throw e;
  });

كما يعمل أيضًا مع ملف يتم استرجاعه من عنوان URL بعيد، ويجب استرجاعه بهذه الطريقة:

Axios.get(file.slackUrl, {
   responseType: "arraybuffer",
   headers: { Authorization: "Bearer " + this.slackToken },
})

المفتاح هنا هو: responseType: "arraybuffer".