Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
266 views
in Technique[技术] by (71.8m points)

node.js - Get image from Axios and send as Form Data to Wordpress API in a Cloud Function

What I'm trying to accomplish is using a Firebase Cloud Function (Node.js) to:

First download an image from an url (f.eg. from unsplash.com) using an axios.get() request

Secondly take that image and upload it to a Wordpress site using the Wordpress Rest API

The problem seems (to me) to be that the formData doesnt actually append any data, but the axios.get() request actually does indeed retrieve a buffered image it seems. Maybe its something wrong I'm doing with the Node.js library form-data or maybe I get the image in the wrong encoding? This is my best (but unsuccessfull) attempt:

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%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&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;
}

I have previously successfully uploaded an image to Wordpress with Javascript in a browser like this:

  async function uploadMediaToWordpress() {
      let formData = new FormData();
      const response = await fetch("https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&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;
  },

I have tried the last couple of days to get this to work but cannot for the life of me seem to get it right. Any pointer in the right direction would be greatly appreciated!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The "regular" JavaScript code (used in a browser) works because the image is sent as a file (see the new File in your code), but your Node.js code is not really doing that, e.g. the Content-Type value is wrong which should be multipart/form-data; boundary=----...... Nonetheless, instead of trying (hard) with the arraybuffer response, I suggest you to use stream just as in the axios documentation and form-data documentation.

So in your case, you'd want to:

  1. Set stream as the responseType:

    axios.get(
        'https://images.unsplash.com/photo-1610303785445-41db41838e3e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80',
        { responseType: 'stream' }
    )
    
  2. Use formData.getHeaders() in the headers of your file upload request (to the /wp/v2/media endpoint):

    axios.post( 'https://wordpresssite.com/wp-json/wp/v2/media', formData, {
        headers: {
            ...formData.getHeaders(),
            Authorization: 'Bearer ...'
        },
    } )
    
  3. And because the remote image from Unsplash.com does not use a static name (e.g. image-name.jpg), then you'll need to set the name when you call formData.append():

    formData.append( 'file', response.data, 'your-custom-image-name.jpeg' );
    

I hope that helps, which worked fine for me (using the node command for Node.js version 14.15.4, the latest release as of writing).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...