Back to Blog
Lesson 32 of the Intermediate WordPress Plugins: REST API & React Admin course
WordPressJune 26, 20263 min read

Managing File Uploads via REST API in WordPress Plugins

Learn to handle file uploads in the WordPress REST API. We'll cover multipart/form-data, media attachment, and securing file processing in your plugin.

WordPressREST APIMediaFile UploadPHPReactplugin-development

Previously in this course, we explored building search and filter functionality in the WordPress REST API to improve data retrieval. Today, we advance our Knowledge Base plugin by enabling users to upload and attach media directly through our admin interface.

Handling file uploads via the REST API is different from standard JSON-based requests because files require multipart/form-data encoding. We need to bridge the gap between binary file streams and WordPress's media management system.

The First Principles of Media Uploads

In WordPress, media is just another post type (attachment). When you upload a file, WordPress creates a post entry, generates metadata, and stores the file in the uploads directory.

To do this via the REST API, we must:

  1. Handle the multipart request: Browser-side, we use FormData to package the file.
  2. Process the upload in PHP: We intercept the request, use media_handle_upload (or wp_handle_upload), and create an attachment post.
  3. Link the media: Update our Knowledge Base post meta to associate the new attachment ID.

Implementing the Media Upload Endpoint

We need a dedicated endpoint for uploads. Using the POST method is standard here. We will use media_handle_upload because it handles the heavy lifting: moving the file, generating thumbnails, and creating the attachment post record.

PHP
#6A9955">// In your REST API class
public function register_routes() {
    register_rest_route('kb/v1', '/upload', [
        'methods'             => 'POST',
        'callback'            => [$this, 'handle_upload'],
        'permission_callback' => [$this, 'permissions_check'],
    ]);
}

public function handle_upload($request) {
    if (empty($_FILES['file'])) {
        return new WP_Error('no_file', 'No file uploaded', ['status' => 400]);
    }

    require_once ABSPATH . 'wp-admin/includes/image.php';
    require_once ABSPATH . 'wp-admin/includes/file.php';
    require_once ABSPATH . 'wp-admin/includes/media.php';

    $attachment_id = media_handle_upload('file', 0);

    if (is_wp_error($attachment_id)) {
        return $attachment_id;
    }

    return ['id' => $attachment_id, 'url' => wp_get_attachment_url($attachment_id)];
}

Linking Media to Custom Posts

Once you have the $attachment_id, you can link it to your Knowledge Base entry. Since we already covered creating POST endpoints for data submission, you should update your existing update endpoint to accept an attachment_id and store it as post meta:

PHP
update_post_meta($post_id, '_kb_featured_image', absint($request['attachment_id']));

Hands-on Exercise: The React Upload Component

In your React admin dashboard, you cannot use the standard apiFetch JSON body. You must construct a FormData object.

  1. Create a file input in your component.
  2. On change, capture the file: const file = event.target.files[0];.
  3. Build the form data:
    JAVASCRIPT
    const formData = new FormData();
    formData.append(CE9178">'file', file);
    
    const response = await apiFetch({
        path: CE9178">'/kb/v1/upload',
        method: CE9178">'POST',
        body: formData, // apiFetch handles multipart headers automatically
    });
  4. Task: Implement a simple file input in your Knowledge Base form that triggers this request, retrieves the ID, and stores it in your local component state to be sent with the final post submission.

Common Pitfalls

  • Missing Includes: media_handle_upload is not loaded by default on the frontend. You must include media.php as shown above, or WordPress will throw a fatal error.
  • Permissions: Always ensure your permission_callback checks for upload_files capability. Never allow anonymous uploads.
  • PHP Memory: Large uploads can hit upload_max_filesize or post_max_size limits in php.ini. If the API returns a 500 error on large files, check your server configuration.
  • Nonce Verification: Like any other POST request, ensure you are passing the correct nonce, as discussed in our implementing nonce verification lesson.

Recap

We have enabled file uploads by creating a dedicated REST endpoint using media_handle_upload. By pairing this with FormData in React, we allow seamless attachment management within our plugin. This completes the media pipeline for our Knowledge Base.

Up next: Optimizing API Response Times, where we will implement object caching to keep our endpoints snappy.

Similar Posts