How to send multipart form data to WordPress endpoint

I built custom React/Gatsby multipart form with file upload and I want to send all form data to WordPress endpoint, upload files to specific folder and display all of the data in the WordPress backend.

This is how I send data:

const {
    stepOne,
    stepTwo,
  } = useContext(FormStepProvider)

  const steps = {
    stepOne: stepOne,
    stepTwo: stepTwo,
  }

  const postData = async () = {
    const formData = new FormData()

    formData.append(stepOne, JSON.stringify(stepOne))
    formData.append(stepTwo, stepTwo.file)

    await fetch(https://panel.domain.com/wp-json/test/v1/forms, {
      method: POST,
      headers: {
        Content-Type: multipart/form-data,
      },

      body: formData,
    })
      .then(response = response)
      .then(result = {
        console.log(Success:, result)
      })
      .catch(error = {
        console.error(Error:, error)
      })
  }

  useEffect(() = {
    postData()
    console.log(steps)
  }, [])

This is the response I get:

This is my endpoint:

add_action( 'rest_api_init', function () {
  register_rest_route( 'test/v1', 'forms', array(
    'methods' = 'POST',
    'callback' = 'get_formdata_function',
    'args'     = array(),
  ) );
} );

function get_formdata_function(WP_REST_Request $request)
{
    $data = $request-get_body();
    print_r($data);
}

I'm new to WordPress and I want to know what's the best way to do this?

Topic endpoints rest-api forms Wordpress

Category Web


So I don't know what stepTwo.file is, but I presumed it's a File object instance, and I believe the issue here is that you're not aware that you didn't actually need to manually set the Content-Type header because when the request body is a FormData instance, then the content type header will always default to multipart/form-data.

Therefore just get rid of that header from the headers list in your fetch() call and then in your endpoint callback, use WP_REST_Request::get_file_params() to get the uploaded file data (name, temporary path, size, etc.). So for example, you could do $request->get_file_params()['stepTwo']. ($_FILES['stepTwo'] would also work, but I'd use the class method)

As for the stepOne parameter (which would be stored in the $_POST array), you could simply do $request['stepOne'] to get the value, or you could also do $request->get_param( 'stepOne' ).

See https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#arguments for more details.

Additionally, you should always set permission_callback, so for example if your REST API endpoint is public, you could do 'permission_callback' => '__return_true'.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.