Contents
Introducción
Este tutorial explica, paso a paso y con todo lujo de detalles, cómo crear un bloque de Gutenberg que permita subir o seleccionar archivos y guardarlos en la Biblioteca de Medios de WordPress usando JavaScript (React APIs de WP). Incluye ejemplos de código listos para usar: el PHP necesario para registrar y encolar los scripts del bloque, el JavaScript del bloque (usando MediaUpload y un media frame personalizado) y una alternativa avanzada mediante la REST API para subir archivos directamente. También se tratan seguridad, permisos y buenas prácticas.
Requisitos y buenas prácticas
- WordPress 5.0 (Gutenberg integrado) o cualquier instalación con soporte de bloques.
- Conocimientos básicos de JS (ESNext/JSX) y PHP.
- Uso recomendado de @wordpress/scripts para build (wp-scripts).
- Comprueba que el usuario que vaya a subir archivos tenga la capacidad upload_files.
- Usar nonces para llamadas REST seguras (wp_create_nonce(wp_rest)).
Estructura mínima del plugin/proyecto
Ejemplo de estructura recomendada:
- my-media-block/
- my-media-block.php (archivo principal del plugin)
- src/
- block.js (código del bloque)
- build/
- block.js (archivo resultante tras build)
- package.json
1) Archivo PHP principal: registrar y encolar
En el archivo principal del plugin registramos el script del bloque y pasamos datos útiles (por ejemplo nonce y siteUrl) para llamadas REST. A continuación un ejemplo mínimo.
wp_create_nonce( wp_rest ),
siteUrl => get_site_url(),
) )
register_block_type( bmu/media-uploader, array(
editor_script => bmu-block,
) )
}
add_action( init, bmu_register_block )
Render dinámico opcional
Si quieres que el bloque renderice en el frontend a partir de los atributos puedes registrarlo con render_callback. Ejemplo sencillo:
function bmu_render_block( attributes ) {
id = isset( attributes[mediaId] ) ? intval( attributes[mediaId] ) : 0
url = isset( attributes[mediaUrl] ) ? esc_url( attributes[mediaUrl] ) :
name = isset( attributes[filename] ) ? esc_html( attributes[filename] ) :
if ( ! id ! url ) {
return No hay archivo seleccionado.
}
return sprintf(
,
url,
name ? name : Descargar archivo
)
}
register_block_type( bmu/media-uploader, array(
editor_script => bmu-block,
render_callback => bmu_render_block,
) )
2) package.json mínimo para build
Si usas @wordpress/scripts, este package.json proporciona scripts para build y start durante el desarrollo.
{
name: bmu,
version: 1.0.0,
scripts: {
build: wp-scripts build,
start: wp-scripts start
},
devDependencies: {
@wordpress/scripts: ^24.0.0
}
}
3) Código del bloque (JS) – ejemplo usando MediaUpload
La forma más sencilla para permitir que un usuario suba o seleccione un archivo es usar el componente MediaUpload de @wordpress/block-editor. Este componente abre la ventana de medios de WP y permite subir o elegir archivos. Al seleccionar devuelve el objeto de adjunto.
import { registerBlockType } from @wordpress/blocks
import { MediaUpload, MediaUploadCheck } from @wordpress/block-editor
import { Button } from @wordpress/components
import { Fragment } from @wordpress/element
registerBlockType( bmu/media-uploader, {
title: Subir archivo a Media Library,
category: media,
attributes: {
mediaId: { type: number },
mediaUrl: { type: string },
filename: { type: string }
},
edit: ( { attributes, setAttributes } ) => {
const { mediaId, mediaUrl, filename } = attributes
const onSelectMedia = ( media ) => {
if ( ! media ! media.id ) return
setAttributes({
mediaId: media.id,
mediaUrl: media.url media.sizes?.full?.url media.source_url,
filename: media.title?.raw media.filename
})
}
const removeMedia = () => {
setAttributes({ mediaId: undefined, mediaUrl: undefined, filename: undefined })
}
return (
{ mediaUrl ? (
Archivo: { filename } (ID: { mediaId })
) : (
(
) }
/>
) }
)
},
save: () => {
return null // se usa render_callback o atributos guardados.
}
} )
Notas sobre MediaUpload
- MediaUpload permite que el usuario suba (pestaña Subir archivos) o seleccione de la biblioteca.
- El objeto devuelto en onSelect contiene id, url/source_url, title, filename, mime_type, sizes, etc.
- Usa allowedTypes para filtrar tipos MIME (por ejemplo image o [application/pdf]).
4) Alternativa: usar un media frame personalizado (window.wp.media)
Si necesitas más control (por ejemplo configurar estado, multiple, título, botones o escuchar eventos concretos), puedes abrir un frame personalizado con window.wp.media. Este ejemplo abre el modal y obtiene el archivo seleccionado o subido.
// abrir un frame personalizado:
const openMediaFrame = () => {
const wpMedia = window.wp window.wp.media
if ( ! wpMedia ) return
const frame = wpMedia({
title: Seleccionar o subir archivo,
button: { text: Usar este archivo },
multiple: false
})
frame.on( select, () => {
const selection = frame.state().get(selection).first().toJSON()
// selection contiene id, url, filename, etc.
setAttributes({
mediaId: selection.id,
mediaUrl: selection.url selection.source_url,
filename: selection.title selection.filename
})
})
frame.open()
}
5) Opción avanzada: subir directamente mediante la REST API (/wp/v2/media)
Si quieres subir el archivo desde el cliente sin usar el modal (por ejemplo arrastrando y soltando un archivo y subirlo automáticamente), usa la ruta /wp/v2/media. Es imprescindible enviar la cabecera X-WP-Nonce para autenticar la petición. En el ejemplo siguiente se asume que en el script hemos inyectado bmuData.nonce y bmuData.siteUrl.
// subir archivo directamente a /wp/v2/media
async function uploadFileDirectly( file ) {
const form = new FormData()
form.append( file, file, file.name )
const response = await fetch( bmuData.siteUrl /wp-json/wp/v2/media, {
method: POST,
headers: {
X-WP-Nonce: bmuData.nonce
},
body: form
} )
if ( ! response.ok ) {
const err = await response.text()
throw new Error( Error subiendo: err )
}
const json = await response.json()
// json.id, json.source_url
return json
}
Puntos importantes sobre la REST API
- El usuario que realice la subida debe tener la capacidad upload_files.
- Controla los tipos MIME y tamaños en el servidor si es necesario.
- Comprueba y gestiona errores (código 400/403/413, etc.).
6) Guardar atributos y renderizado
Recomendación: guarda en los atributos al menos mediaId (ID del adjunto) y mediaUrl (URL). El ID permite realizar operaciones adicionales (por ejemplo actualizar la información del adjunto). Para el frontend puedes usar render_callback en PHP (ver ejemplo de PHP arriba) o guardar un HTML estático en save().
7) Permisos, seguridad y validaciones
- Usa nonces: genera con wp_create_nonce(wp_rest) y pásalo con wp_localize_script para las llamadas REST.
- Comprueba capacidades del usuario (current_user_can(upload_files)) si haces lógica en PHP.
- Valida los tipos MIME y tamaños en el servidor (no confíes solo en el cliente).
- Escapa salidas en PHP con esc_url() / esc_html() si renderizas en el servidor.
8) Errores comunes y cómo solucionarlos
- El modal no se abre: asegúrate de que window.wp.media está cargado en editor debe estar presente si las dependencias están bien encoladas.
- 403 en la subida REST: nonce inválido o falta capacidad revisa X-WP-Nonce y current_user_can.
- URL incorrecta tras seleccionar: revisa las propiedades del objeto devuelto (source_url, url, sizes).
- Permisos CORS en instalaciones headless: tendrás que configurar cabeceras o auth adecuada.
9) Tips finales y mejoras
- Soporta múltiples archivos configurando multiple={true} y guardando un array de IDs/URLs.
- Muestra previsualizaciones usando los tamaños disponibles en media.sizes.
- Permite reordenar y eliminar archivos si es una galería/colección.
- Considera crear un control personalizado que combine drag drop subida vía REST y posterior selección por ID.
- Versiona y cachea correctamente el script en PHP usando filemtime para busting en producción.
Recapitulación rápida
- La forma más simple: usar MediaUpload para abrir la ventana de medios (soporta subida automática).
- Para control extra: usar window.wp.media para crear frames personalizados.
- Para subir sin UI: usar la ruta REST /wp/v2/media con nonce y FormData.
- Siempre valida permisos y escapa las salidas cuando renderices en el frontend.
Enlaces útiles
Conclusión
Con estas piezas tienes todo lo necesario para crear un bloque de Gutenberg que permita subir y seleccionar archivos en la Biblioteca de Medios mediante JS. Elige la aproximación (MediaUpload, media frame personalizado o REST API) que mejor se adapte a tu caso de uso, y aplica las comprobaciones de seguridad y validaciones descritas para garantizar robustez en producción.
|
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |
