Получить изображение из Axios и отправить в виде данных формы в API WordPress в облачной функции

#node.js #wordpress #axios #google-cloud-functions #multipartform-data

#node.js #wordpress #axios #google-cloud-функции #multipartform-данные

Вопрос:

Чего я пытаюсь добиться, так это использования облачной функции Firebase (Node.js ) к:

Сначала загрузите изображение с URL-адреса (f.eg . из unsplash.com ) использование axios.get() запроса

Во-вторых, возьмите это изображение и загрузите его на сайт WordPress с помощью WordPress Rest API

Проблема (для меня) заключается в том, что на самом formData деле не добавляются какие-либо данные, но axios.get() запрос на самом деле действительно извлекает буферизованное изображение, как кажется. Может быть, что-то не так, что я делаю с Node.js библиотечная форма-данные или, может быть, я получаю изображение в неправильной кодировке? Это моя лучшая (но безуспешная) попытка:

 async function uploadMediaToWordpress() {
  var FormData = require("form-data");

    var formData = new FormData();
    var response = await axios.get(
      "https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw=amp;ixlib=rb-1.2.1amp;auto=formatamp;fit=cropamp;w=634amp;q=80"
      { responseType: "arraybuffer" }
    );
    formData.append("file", response.data);

    try {
      var uploadedMedia = await axios.post("https://wordpresssite.com/wp-json/wp/v2/media",
        formData, {
          headers: {
            "Content-Disposition": 'form-data; filename="example.jpeg"',
            "Content-Type": "image/jpeg",
            Authorization: "Bearer <jwt_token>",
          },
      });
    } catch (error) {
      console.log(error);
      throw new functions.https.HttpsError("failed-precondition", "WP media upload failed");
    }
    return uploadedMedia.data;
}
 

Ранее я успешно загрузил изображение в WordPress с помощью Javascript в браузере, подобном этому:

   async function uploadMediaToWordpress() {
      let formData = new FormData();
      const response = await fetch("https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw=amp;ixlib=rb-1.2.1amp;auto=formatamp;fit=cropamp;w=634amp;q=80");
      const blob = await response.blob();
      const file = new File([blob], "image.jpeg", { type: blob.type }); 

      formData.append("file", file);
      var uploadedMedia = await axios.post("https://wordpresssite.com/wp-json/wp/v2/media",
        formData, {
          headers: {
            "Content-Disposition": 'form-data; filename="example.jpeg"',
            "Content-Type": "image/jpeg",
            Authorization: "Bearer <jwt_token>",
          },
      });
      return uploadedMedia.data;
  },
 

Последние пару дней я пытался заставить это работать, но, похоже, не могу понять, что это правильно. Любой указатель в правильном направлении был бы очень признателен!

Комментарии:

1. попробуйте без Content-Type Content-Disposition заголовка и в вашем запросе

Ответ №1:

«Обычный» код JavaScript (используемый в браузере) работает, потому что изображение отправляется в виде файла (см. new File В Вашем коде), но ваш Node.js код на самом деле этого не делает, например Content-Type , значение неверно, как и должно быть multipart/form-data; boundary=----..... . Тем не менее, вместо того, чтобы пытаться (усердно) с arraybuffer ответом, я предлагаю вам использовать stream так же, как в документации axios и документации form-data.

Итак, в вашем случае вы хотели бы:

  1. Установить stream в качестве responseType :
     axios.get(
        'https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw=amp;ixlib=rb-1.2.1amp;auto=formatamp;fit=cropamp;w=634amp;q=80',
        { responseType: 'stream' }
    )
     
  2. Используйте formData.getHeaders() в headers вашем запросе на загрузку файла (в /wp/v2/media конечную точку):
     axios.post( 'https://wordpresssite.com/wp-json/wp/v2/media', formData, {
        headers: {
            ...formData.getHeaders(),
            Authorization: 'Bearer ...'
        },
    } )
     
  3. И поскольку удаленное изображение из Unsplash.com не использует статическое имя (например image-name.jpg ,), тогда вам нужно будет задать это имя при вызове formData.append() :
     formData.append( 'file', response.data, 'your-custom-image-name.jpeg' );
     

Я надеюсь, что это поможет, что отлично сработало для меня (используя node команду для Node.js версия 14.15.4, последняя версия на момент написания).

Комментарии:

1. Спасибо за это объяснение, оно работает сейчас! Один вопрос, есть ли возможность узнать расширение файла изображения, которое я получаю от Unsplash? Или я могу каким-то образом преобразовать его в формат jpg или аналогичный?

2. Вы можете использовать пакет mime , а затем получить расширение с помощью mime.getExtension( response.headers['content-type'] ) . Что касается «принудительно преобразовать его в jpg», я пока не уверен в этом, так что, возможно, вы хотите задать это в другом вопросе .. 🙂

3. Спасибо вам за это, простое и приятное решение! 🙂