Agregar imágenes programáticamente a la biblioteca de medios
Estoy intentando agregar múltiples imágenes programáticamente a la biblioteca de medios. Ya subí las imágenes a wp-content/uploads
, y ahora estoy tratando de usar wp_insert_attachement
.
Aquí está el código, sin embargo no está funcionando como se espera. Creo que los metadatos no se están generando correctamente. Puedo ver los archivos en la biblioteca de medios, pero sin miniatura, y además cuando edito la imagen obtengo un error que me pide volver a subir la imagen.
$filename_array = array(
'article1.jpg',
'article2.jpg',
);
// El ID de la entrada a la que pertenece este adjunto.
$parent_post_id = 0;
// Obtener la ruta al directorio de subidas.
$wp_upload_dir = wp_upload_dir();
foreach ($filename_array as $filename) {
// Verificar el tipo de archivo. Lo usaremos como 'post_mime_type'.
$filetype = wp_check_filetype( basename( $filename ), null );
// Preparar un array de datos para el adjunto.
$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'
);
// Insertar el adjunto.
$attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );
// Asegurarse de que este archivo está incluido, ya que wp_generate_attachment_metadata() depende de él.
require_once( ABSPATH . 'wp-admin/includes/image.php' );
// Generar los metadatos para el adjunto y actualizar el registro en la base de datos.
$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
wp_update_attachment_metadata( $attach_id, $attach_data );
}

$image_url = 'dirección de la imagen'; // URL de la imagen a subir
$upload_dir = wp_upload_dir(); // Obtiene el directorio de subida de WordPress
$image_data = file_get_contents( $image_url ); // Obtiene los datos binarios de la imagen
$filename = basename( $image_url ); // Extrae el nombre del archivo de la URL
// Crea el directorio si no existe y define la ruta del archivo
if ( wp_mkdir_p( $upload_dir['path'] ) ) {
$file = $upload_dir['path'] . '/' . $filename;
}
else {
$file = $upload_dir['basedir'] . '/' . $filename;
}
// Guarda la imagen en el servidor
file_put_contents( $file, $image_data );
// Verifica el tipo de archivo
$wp_filetype = wp_check_filetype( $filename, null );
// Prepara los datos del attachment
$attachment = array(
'post_mime_type' => $wp_filetype['type'], // Tipo MIME
'post_title' => sanitize_file_name( $filename ), // Título sanitizado
'post_content' => '', // Contenido vacío
'post_status' => 'inherit' // Establece el estado
);
// Inserta el attachment en la base de datos
$attach_id = wp_insert_attachment( $attachment, $file );
// Incluye las funciones necesarias para procesar imágenes
require_once( ABSPATH . 'wp-admin/includes/image.php' );
// Genera los metadatos del attachment (tamaños, etc.)
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
// Actualiza los metadatos en la base de datos
wp_update_attachment_metadata( $attach_id, $attach_data );

Archivo descargado pero no hay miniatura disponible, la URL del adjunto también devuelve error 404

@UmairHamid Lo mismo aquí. Esto se debe a que el segundo argumento de wp_insert_attachment
debería ser la ruta del archivo (por lo que $file
en este ejemplo), no el nombre del archivo. Edité la respuesta, esperando aprobación.

Usa wp_get_attachment_image_src
para obtener la URL, ej. wp_get_attachment_image_src($attach_id)
- https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src

Si utilizas la función de carga lateral (sideload) de WordPress, puedes hacer esto más fácilmente (y dejar que WordPress maneje toda la sanitización por ti).
<?php
// ejemplo:
// $file = 'http://www.example.com/image.png';
// $description = 'alguna descripción';
function my_upload_image( $file, $description ) {
$file_array = [ 'name' => wp_basename( $file ), 'tmp_name' => download_url( $file ) ];
// Si hay error al almacenar temporalmente, devuelve el error.
if ( is_wp_error( $file_array['tmp_name'] ) ) {
return $file_array['tmp_name'];
}
// Realiza la validación y almacenamiento.
$id = media_handle_sideload( $file_array, 0, $description );
// Si hay error al almacenar permanentemente, elimina el archivo temporal.
if ( is_wp_error( $id ) ) {
@unlink( $file_array['tmp_name'] );
return $id;
}
return true;
}

Ten en cuenta que esto solo funciona desde dentro de /wp-admin/
. Fuera de ahí, debes asegurarte de hacer require_once
de estos tres archivos:
ABSPATH . 'wp-admin/includes/file.php'
,
ABSPATH . 'wp-admin/includes/media.php'
,
ABSPATH . 'wp-admin/includes/image.php'

Esto también funciona para imágenes ya almacenadas en el servidor, simplemente usa la ruta de la imagen en lugar de download_url( $file )
. Pero si haces esto, ten en cuenta que al usar media_handle_sideload
, la imagen se eliminará automáticamente después del procesamiento. Si no quieres que esto ocurra, simplemente copia la imagen al directorio tmp mediante $tmp_path = get_temp_dir() . basename( $file ); copy( $file, $tmp_path );
, luego puedes usar 'tmp_name' => $tmp_path
en su lugar.

Tuve problemas con la solución de @TrubinE donde los archivos de imagen no se cargaban correctamente.
Aquí hay un ejemplo completo que funcionó para mí: https://gist.github.com/m1r0/f22d5237ee93bcccb0d9
Esta es una idea similar pero utiliza la biblioteca HTTP de WordPress para obtener el contenido en lugar de file_get_contents(). Aquí está el contenido de la solución del gist de github de 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; código aquí

<?php
// método más simple para subir una imagen
$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 significa que la imagen no está asociada a un post
$imgid = media_sideload_image( $url, $image_for_post_id, $title, 'id' );
if ( is_wp_error($imgid) ) {
echo "<br>Error en upload_image_by_url($url): ";
echo $imgid->get_error_message();
return false;
}
else {
echo "<br>upload_image_by_url($url) = $imgid";
return $imgid;
}
}?>

Tal como está escrito actualmente, tu respuesta no es clara. Por favor, [edita] para agregar detalles adicionales que ayuden a otros a entender cómo esto responde a la pregunta planteada. Puedes encontrar más información sobre cómo escribir buenas respuestas en el centro de ayuda.
