Make WordPress Core

Opened 2 months ago

Last modified 18 hours ago

#64915 assigned defect (bug)

Media: Enable HEIC/HEIF uploads when server lacks image editor support

Reported by: adamsilverstein's profile adamsilverstein Owned by: adamsilverstein's profile adamsilverstein
Milestone: 7.1 Priority: normal
Severity: normal Version: trunk
Component: Media Keywords: has-patch
Focuses: Cc:

Description

Description

HEIC (HEIF with HEVC codec) is the default photo format on iPhones. When users upload HEIC images via the REST API and the server's image editor (ImageMagick/GD) doesn't support HEIC, the upload is blocked entirely by the wp_prevent_unsupported_mime_type_uploads check in WP_REST_Attachments_Controller::create_item_permissions_check(), returning a rest_upload_image_type_not_supported error.

With the client-side media processing feature, the browser can decode HEIC images natively using createImageBitmap() — which leverages the OS/browser's licensed HEVC codecs (Safari everywhere, Chrome on macOS, Chrome on Windows with codec extension) — and convert them to JPEG for sub-size generation via canvas. However, this requires the server to first accept the HEIC upload.

Proposed Change

Bypass the $prevent_unsupported_uploads check for HEIC/HEIF MIME types (detected via the existing wp_is_heic_image_mime_type() helper) so the file can be stored on the server even when the image editor can't process it.

The flow becomes:

  1. Upload HEIC to server — server tries to process and generate sub-sizes
  2. If server has HEIC support → everything works as before
  3. If server lacks HEIC support → file is stored, missing_image_sizes is populated in the REST response
  4. Client detects missing sizes and uses browser-native createImageBitmap() + OffscreenCanvas to decode and convert to JPEG
  5. JPEG is sideloaded as the scaled version, sub-sizes are generated from the JPEG via the existing client-side resize pipeline

This approach:

  • Is backwards compatible (servers with HEIC support are unaffected)
  • Leverages browser-licensed HEVC decoding rather than shipping a decoder
  • Uses the existing wp_is_heic_image_mime_type() function already in core

Change Summary

In src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php:

// Always allow HEIC/HEIF uploads through even if the server's image
// editor doesn't support them. The client-side canvas fallback will
// handle processing using the browser's native HEVC decoder.
if (
    $prevent_unsupported_uploads &&
    ! empty( $files['file']['type'] ) &&
    wp_is_heic_image_mime_type( $files['file']['type'] )
) {
    $prevent_unsupported_uploads = false;
}

Testing

  1. Use a WordPress environment where ImageMagick does NOT have HEIC support
  2. Upload a HEIC image via the REST API media endpoint (POST /wp/v2/media)
  3. Verify the upload succeeds (previously returned rest_upload_image_type_not_supported error)
  4. Verify missing_image_sizes is populated in the response

Change History (6)

#1 @adamsilverstein
2 months ago

  • Owner set to adamsilverstein
  • Status changed from new to assigned

This ticket was mentioned in PR #11323 on WordPress/wordpress-develop by @adamsilverstein.


2 months ago
#2

  • Keywords has-patch added

Trac ticket: https://core.trac.wordpress.org/ticket/64915

## What?

Allow HEIC/HEIF image uploads to succeed even when the server's image editor (ImageMagick/GD) doesn't support HEIC. Currently, wp_prevent_unsupported_mime_type_uploads blocks these uploads entirely.

Gutenberg PR: https://github.com/WordPress/gutenberg/pull/76731

## Why?

HEIC is the default photo format on iPhones. When users upload HEIC images and the server can't process them, the upload fails with an unhelpful error. With the client-side media processing feature, the browser can decode HEIC using its native createImageBitmap() API (leveraging OS-licensed HEVC codecs) and convert to JPEG for sub-size generation. But first, the server needs to accept the upload.

## How?

In WP_REST_Attachments_Controller::create_item_permissions_check(), bypass the $prevent_unsupported_uploads check when the uploaded file is HEIC/HEIF (detected via the existing wp_is_heic_image_mime_type() helper). This allows the file to be stored on the server, after which the client-side canvas fallback generates a JPEG version and all required sub-sizes.

## Testing Instructions

  1. Use a WordPress environment where ImageMagick does NOT have HEIC support
  2. Upload a HEIC image via the REST API media endpoint
  3. Verify the upload succeeds (previously would return rest_upload_image_type_not_supported error)
  4. Verify missing_image_sizes is populated in the response (server couldn't generate sub-sizes)

@adamsilverstein commented on PR #11323:


4 weeks ago
#3

Note for follow-up: when r62081 (commit c863860ccf, "Media: Remove client-side media processing feature for now") is reverted to reintroduce client-side media processing in 7.1, the generate_sub_sizes === false skip in WP_REST_Attachments_Controller::create_item_permissions_check() should be restored alongside the HEIC/HEIF allowance added here.

Original block from this PR (dropped during the trunk merge since generate_sub_sizes no longer exists on trunk):

\\\`php
When the client handles image processing (generate_sub_sizes is false),
skip the server-side image editor support check.
if ( false === \$requestgenerate_sub_sizes? ) {

\$prevent_unsupported_uploads = false;

}
\\\`

@ramonopoly commented on PR #11323:


9 days ago
#4

Heads up, there was a follow up to https://github.com/WordPress/gutenberg/pull/76731:

Adds an is_string() guard to gutenberg_delete_heic_companion_file() so it bails on attachments whose wp_get_attachment_metadata()original? is not a string filename.

Not sure if it needs a core sync at all since it's a GB load.php change. 🤔

@adamsilverstein commented on PR #11323:


8 days ago
#5

Not sure if it needs a core sync at all since it's a GB load.php change

Possibly, I will review once the 7.1 branch is open and I am able to reintroduce the feature in core.

Thanks for cross linking this ticket!

#6 @audrasjb
18 hours ago

Removing trunk version as this is not going to be shipped with WP 7.0 but in the next releases.

Note: See TracTickets for help on using tickets.