Программное добавление изображений в медиа-библиотеку
Я пытаюсь программно добавить несколько изображений в медиа-библиотеку. Я загрузил изображения в wp-content/uploads
, теперь пытаюсь использовать wp_insert_attachement
.
Вот код, однако он не работает как ожидалось. Я думаю, что метаданные не генерируются правильно. Я вижу файлы в медиа-библиотеке, но без миниатюр, также при редактировании изображения появляется ошибка с просьбой повторно загрузить изображение.
$filename_array = array(
'article1.jpg',
'article2.jpg',
);
// ID записи, для которой предназначено это вложение
$parent_post_id = 0;
// Получаем путь к директории загрузок
$wp_upload_dir = wp_upload_dir();
foreach ($filename_array as $filename) {
// Проверяем тип файла. Используем это как 'post_mime_type'
$filetype = wp_check_filetype( basename( $filename ), null );
// Подготавливаем массив данных записи для вложения
$attachment = array(
'guid' => $wp_upload_dir['url'] . '/' . basename( $filename ),
'post_mime_type' => $filetype['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
'post_content' => '',
'post_status' => 'inherit'
);
// Вставляем вложение
$attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );
// Убедимся, что этот файл подключен, так как wp_generate_attachment_metadata() зависит от него
require_once( ABSPATH . 'wp-admin/includes/image.php' );
// Генерируем метаданные для вложения и обновляем запись в базе данных
$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
wp_update_attachment_metadata( $attach_id, $attach_data );
}

$image_url = 'адрес изображения';
$upload_dir = wp_upload_dir();
$image_data = file_get_contents( $image_url );
$filename = basename( $image_url );
if ( wp_mkdir_p( $upload_dir['path'] ) ) {
$file = $upload_dir['path'] . '/' . $filename;
}
else {
$file = $upload_dir['basedir'] . '/' . $filename;
}
file_put_contents( $file, $image_data );
$wp_filetype = wp_check_filetype( $filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name( $filename ),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );

Файл загружен, но миниатюра недоступна, ссылка на вложение также возвращает 404

@UmairHamid То же самое. Это происходит потому, что второй аргумент wp_insert_attachment
должен быть путем к файлу (в данном случае $file
), а не именем файла. Я отредактировал ответ, ожидаю подтверждения.

Используйте wp_get_attachment_image_src
для получения URL, например: wp_get_attachment_image_src($attach_id)
- https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src

Если вы используете функцию WordPress для загрузки файлов с внешних источников (sideload), вы можете сделать это проще (и позволить WordPress самому обрабатывать всю очистку данных).
<?php
// пример:
// $file = 'http://www.example.com/image.png';
// $description = 'какое-то описание';
function my_upload_image( $file, $description ) {
$file_array = [ 'name' => wp_basename( $file ), 'tmp_name' => download_url( $file ) ];
// Если произошла ошибка при временном сохранении, возвращаем ошибку.
if ( is_wp_error( $file_array['tmp_name'] ) ) {
return $file_array['tmp_name'];
}
// Выполняем проверку и сохранение файла.
$id = media_handle_sideload( $file_array, 0, $description );
// Если произошла ошибка при постоянном сохранении, удаляем временный файл.
if ( is_wp_error( $id ) ) {
@unlink( $file_array['tmp_name'] );
return $id;
}
return true;
}

Имейте в виду, что это работает только из /wp-admin/
. Вне его вам нужно убедиться, что вы подключаете эти три файла через require_once
:
ABSPATH . 'wp-admin/includes/file.php'
,
ABSPATH . 'wp-admin/includes/media.php'
,
ABSPATH . 'wp-admin/includes/image.php'

Это также работает для изображений, уже хранящихся на сервере — вы просто используете путь к изображению вместо download_url( $file )
. Но если вы делаете так, учтите, что при использовании media_handle_sideload
изображение будет автоматически удалено после обработки. Если вы хотите этого избежать, просто скопируйте изображение во временную директорию с помощью $tmp_path = get_temp_dir() . basename( $file ); copy( $file, $tmp_path );
, и затем можете использовать 'tmp_name' => $tmp_path
.

У меня возникли проблемы с решением от @TrubinE, когда файлы изображений не загружались.
Вот полный пример, который сработал у меня: https://gist.github.com/m1r0/f22d5237ee93bcccb0d9
Это похожая идея, но использует библиотеку WP HTTP для получения содержимого вместо file_get_contents(). Вот содержимое решения из github gist от m1r0:
if ( ! class_exists( 'WP_Http' ) ) {
include_once( ABSPATH . WPINC . '/class-http.php' );
}
$http = new WP_Http();
$response = $http->request( $meta['image_url'] );
if ( $response['response']['code'] !== 200 ) {
return false;
}
$upload = wp_upload_bits( basename( $meta['image_url'] ), null, $response['body'] );
if ( !empty( $upload['error'] ) ) {
return false;
}
$file_path = $upload['file'];
$file_name = basename( $file_path );
$file_type = wp_check_filetype( $file_name, null );
$attachment_title = sanitize_file_name( pathinfo( $file_name, PATHINFO_FILENAME ) );
$wp_upload_dir = wp_upload_dir();
$post_info = array(
'guid' => $wp_upload_dir['url'] . '/' . $file_name,
'post_mime_type' => $file_type['type'],
'post_title' => $attachment_title,
'post_content' => '',
'post_status' => 'inherit',
);
$attach_id = wp_insert_attachment( $post_info, $file_path, $parent_post_id );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attach_data = wp_generate_attachment_metadata( $attach_id, $file_path );
wp_update_attachment_metadata( $attach_id, $attach_data );
return $attach_id; code here

`<?php
// простейший метод загрузки изображения
$url_image = "http://example.com/any_image.jpg" ;
$new_image_id = upload_image_by_url ( $url_image );
function upload_image_by_url ($url) {
$title = basename($url) ;
$image_for_post_id = 0 ; // 0 означает, что изображение не привязано к записи
$imgid = media_sideload_image( $url, $image_for_post_id, $title, 'id' );
if ( is_wp_error($imgid) ) {
echo "<br>Ошибка upload_image_by_url($url): ";
echo $imgid->get_error_message();
return false;
}
else {
echo "<br>upload_image_by_url($url) = $imgid";
return $imgid;
}
}?>`

В текущем виде ваш ответ непонятен. Пожалуйста, [отредактируйте] его, чтобы добавить дополнительные детали, которые помогут другим понять, как это решает заданный вопрос. Вы можете найти больше информации о том, как писать хорошие ответы, в справочном центре.
