# Как загрузить SVG в WordPress
По умолчанию в WordPress нельзя загружать файлы формата SVG из соображений безопасности. Но что делать, если вам это действительно нужно? Есть решение!
 Когда вы пытаетесь загрузить SVG, появляется сообщение: "Извините, этот тип файла не разрешен по соображениям безопасности".
Если вам интересно, почему загрузка SVG запрещена по умолчанию в WordPress и с чем это связано, вы можете ознакомиться с тикетом #24251 "Пересмотреть включение SVG в список допустимых типов файлов".
Если вам проще, вы можете использовать плагин **Safe SVG**. Он позволяет загружать SVG и при этом очищает код загружаемого файла от вредоносных элементов.
## Шаг 1 - Включение SVG в список разрешенных файлов
Для этого мы используем хук upload_mimes
, который позволяет изменить список файлов, доступных для загрузки, по их MIME-типам.
```php
add_filter( 'upload_mimes', 'svg_upload_allow' );
// Добавляет SVG в список разрешенных типов файлов.
function svg_upload_allow( $mimes ) {
$mimes['svg'] = 'image/svg+xml';
return $mimes;
}
Иногда этого кода достаточно, но не для всех SVG-файлов. Давайте разберемся почему.
Настоящий MIME-тип SVG файла, который определяется в WordPress с помощью функции php finfo_file()
, может быть двух вариантов:
image/svg+xml
— когда SVG-код имеет заголовок XML.image/svg
— когда SVG-код содержит только тег<svg>
без заголовков.
Оба этих варианта нужно добавить, но так как можно добавить только один, одного кода недостаточно, поэтому нужно выполнить второй шаг.
Шаг 2 - Замена MIME-типа SVG
Как упоминалось ранее, предыдущего кода недостаточно. Причина в том, что в результате проверки и несоответствия указанного MIME-типа реальному (который определяется WordPress), MIME-тип просто будет сброшен в ноль. Для этого нам поможет хук wp_check_filetype_and_ext
.
add_filter( 'wp_check_filetype_and_ext', 'fix_svg_mime_type', 10, 5 );
// Исправляем MIME-тип для SVG-файлов.
function fix_svg_mime_type( $data, $file, $filename, $mimes, $real_mime = '' ) {
// WordPress 5.1 и выше
if( version_compare( $GLOBALS['wp_version'], '5.1.0', '>=' ) ) {
$dosvg = in_array( $real_mime, [ 'image/svg', 'image/svg+xml' ] );
} else {
$dosvg = ( '.svg' === strtolower( substr( $filename, -4 ) ) );
}
// Если MIME-тип был сброшен, исправим его и проверим права пользователя
if( $dosvg ) {
// Разрешить
if( current_user_can('manage_options') ) {
$data['ext'] = 'svg';
$data['type'] = 'image/svg+xml';
}
// Запре��ить
else {
$data['ext'] = false;
$data['type'] = false;
}
}
return $data;
}
Если вы уберете проверку прав администратора из приведенного выше кода, он станет небезопасным и может открыть уязвимость на вашем сайте.
В приведенном коде есть проверка версии WordPress. Начиная с версии 5.1.0, благодаря тикету разработчика, появился параметр $real_mime
, который позволяет более надежно проверять файл по его коду, а не по расширению.
Я также рекомендую ограничить размер загружаемого SVG файла. Например, не более 50 КБ. SVG-файлы обычно маленькие, и большой размер может указывать на наличие плохого кода в файле.
Кода выше достаточно, чтобы WordPress разрешил загрузку SVG в медиа-библиотеку. Следующий шаг — это визуализация.
Отображение SVG в медиа-библиотеке
После выполнения описанных выше шагов SVG-файлы будут отображаться как документы, а не как изображения:
Код, отвечающий за отображение этих блоков изображений, создается функцией wp_print_media_templates()
из файла wp-includes/media-template.php
:
<# if ( data.uploading ) { #>
<# } else { #>
<# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
<# } else if ( data.sizes && data.sizes.medium ) { #>
<# } else { #>
<# } #>
{{ data.filename }}
<# } #>
<# } else if ( 'image' === data.type && data.sizes ) { #>
Смысл кода заключается в следующем: если изображение имеет свойство src
(ссылка на изображение) и оно не равно ссылке на иконку документа (поскольку любой файл по сути является документом), или если изображение имеет размер medium (SVG-файлы не обрезаются).
Так как у SVG-файлов нет ни того, ни другого, нам нужно смоделировать один из этих вариантов, а для этого поможет фильтр wp_prepare_attachment_for_js
.
Вариант 1 - С отображением имени файла
add_filter( 'wp_prepare_attachment_for_js', 'show_svg_in_media_library' );
// Формирует данные для отображения SVG как изображения в медиа-библиотеке.
function show_svg_in_media_library( $response ) {
if ( $response['mime'] === 'image/svg+xml' ) {
// С отображе��ием имени файла
$response['image'] = [
'src' => $response['url'],
];
}
return $response;
}
Вариант 2 - Без отображения имени файла
add_filter( 'wp_prepare_attachment_for_js', 'show_svg_in_media_library' );
// Формирует данные для отображения SVG как изображения в медиа-библиотеке.
function show_svg_in_media_library( $response ) {
if ( $response['mime'] === 'image/svg+xml' ) {
// Без отображения имени файла
$response['sizes'] = [
'medium' => [
'url' => $response['url'],
],
// при редактировании изображения
'full' => [
'url' => $response['url'],
],
];
}
return $response;
}
Полный класс
Вот пример класса, который вы можете использовать:
=' ) ) {
$dosvg = in_array( $real_mime, [ 'image/svg', 'image/svg+xml' ] );
} else {
$dosvg = ( '.svg' === strtolower( substr( $filename, -4 ) ) );
}
// Если MIME-тип был сброшен, исправим его
if( $dosvg ) {
if( current_user_can( 'upload_files' ) ) {
$data['ext'] = 'svg';
$data['type'] = 'image/svg+xml';
} else {
// Запретить
$data['ext'] = $type_and_ext['type'] = false;
}
}
return $data;
}
/**
* Генерирует данные для отображения SVG как изображений в медиа-библиотеке.
*/
public static function show_svg_in_media_library( $response ) {
if ( $response['mime'] === 'image/svg+xml' ) {
$response['sizes'] = [
'medium' => [
'url' => $response['url'],
],
// при редактировании изображения
'full' => [
'url' => $response['url'],
],
];
}
return $response;
}
/**
* Ограничить размер загружаемых файлов по типу
*/
public static function check_upload_file_size( $file ) {
if( ! $file ) {
return $file;
}
// для SVG
if( str_contains( ( $file['type'] ?? '' ), 'image/svg+xml' ) ) {
$size_limit = 50 * 1024; // допустимый размер в КБ
if( (int) $file['size'] > $size_limit ) {
$file['error'] = sprintf(
__( 'ОШИБКА: Размер этого типа файлов не может превышать %s', 'km' ),
size_format( $size_limit )
);
}
}
return $file;
}
}
Теперь вы можете загружать SVG-файлы в WordPress, используя описанные выше методы.