Cómo migrar ficheros e imágenes con Drupal a un campo media

Client
  • Omitsis
Technologies
Services
Date
  • 11/01/2026

Cuando migramos contenido a Drupal desde otra fuente (CSV, Drupal 7, sistemas externos, etc.), es muy común trabajar con imágenes y archivos. Desde Drupal 8 y especialmente en Drupal 9–11, las entidades Media son la forma recomendada de manejar imágenes y archivos en lugar de usar campos de imagen/archivo directamente.

Este artículo explica cómo migrar imágenes a entidades Media usando Migrate, paso a paso, y luego referenciar esas entidades Media desde el contenido. Los ejemplos están basados en una fuente CSV, pero los mismos conceptos aplican a otras fuentes.

¿Por qué usar Media en lugar de campos file/image?

El módulo Media ha estado en el núcleo de Drupal durante años y es maduro y estable en Drupal 10 y Drupal 11. Usar entidades Media te ofrece:

  • Imágenes y archivos reutilizables entre contenidos
  • Una biblioteca de medios centralizada
  • Campos adicionales en los medios (copyright, autor, alt por defecto, etc.)
  • Mejor experiencia editorial

En Omitsis, usar Media es ahora, y desde hace años, un estándar por defecto para proyectos Drupal.

La desventaja es que migrar a Media es ligeramente más complejo que migrar directamente a campos file. Este artículo se enfoca en resolver eso.

Prerrequisitos

Este artículo asume conocimientos básicos de la API de Migrate.

Si eres nuevo en migraciones, se recomienda leer primero una introducción sobre migración desde CSV usando el módulo Migrate.

No usaremos helpers de contrib como migrate_files_to_media. En su lugar, nos basaremos únicamente en plugins de migrate del core/contrib para que entiendas completamente lo que está sucediendo.

Módulos requeridos (Drupal 10 / 11)

Instala los módulos requeridos vía Composer:

composer require drupal/migrate_plus drupal/migrate_tools drupal/migrate_source_csv drupal/config_devel

Habilítalos:

drush en -y migrate migrate_plus migrate_tools migrate_source_csv config_devel

config_devel es opcional pero muy conveniente durante el desarrollo para auto-instalar archivos YAML de migración.

Resumen de la estrategia de migración

Dividiremos el proceso en tres migraciones:

  1. Migración de archivos – copiar archivos de imagen a Drupal y crear entidades file
  2. Migración de Media – crear entidades media:image referenciando esos archivos
  3. Migración de contenido – crear nodos referenciando las entidades Media

Esta separación hace que las migraciones sean más fáciles de depurar, re-ejecutar y reutilizar.

1. Migrando archivos de imagen

Primero, migramos los archivos físicos de imagen y creamos entidades file.

Archivo de migración: migrate_plus.migration.migrate_files.yml

id: migrate_files
label: Migrate Files

source:
  plugin: csv
  path: modules/custom/custom_migrate/data/products.csv
  delimiter: ','
  enclosure: '"'
  header_offset: 0
  ids:
    - code
  fields:
    0:
      name: cat
      label: 'Category'
    1:
      name: code
      label: 'Product code'
    2:
      name: title
      label: 'Title'
    3:
      name: image
      label: 'Image'

constants:
  file_source_uri: 'public://import/source/images'
  file_dest_uri: 'public://imports/dest/images'

process:
  file_source:
    - plugin: concat
      delimiter: '/'
      source:
        - constants/file_source_uri
        - image
    - plugin: urlencode

  file_dest:
    - plugin: concat
      delimiter: '/'
      source:
        - constants/file_dest_uri
        - image
    - plugin: urlencode

  uri:
    plugin: file_copy
    source:
      - '@file_source'
      - '@file_dest'

  uid:
    plugin: default_value
    default_value: 1

destination:
  plugin: entity:file

Puntos clave

  • Las constantes definen los directorios de origen y destino
  • file_copy copia la imagen y crea una entidad file
  • El CSV solo contiene el nombre del archivo de imagen, no rutas completas
  • file_copy soporta opciones de overwrite y reuse si es necesario

En este punto, Drupal conoce los archivos, pero aún no como Media.

2. Creando entidades Media desde archivos

Ahora convertimos los archivos en entidades media:image.

Archivo de migración: migrate_plus.migration.media_images.yml

id: media_images
label: Media images

source:
  plugin: csv
  path: modules/custom/custom_migrate/data/products.csv
  delimiter: ','
  enclosure: '"'
  header_offset: 0
  ids:
    - code
  fields:
    0:
      name: cat
      label: 'Category'
    1:
      name: code
      label: 'Product code'
    2:
      name: title
      label: 'Title'
    3:
      name: image
      label: 'Image'

process:
  # Evitar crear entidades media duplicadas
  skip:
    - plugin: entity_lookup
      entity_type: media
      bundle: image
      value_key: name
      source: image
      ignore_case: true
      access_check: false
    - plugin: skip_on_not_empty
      method: row
      message: 'Skipping already existing media'

  field_media_image/target_id:
    plugin: migration_lookup
    migration: migrate_files
    source: code
    no_stub: true

  uid:
    plugin: default_value
    default_value: 1

destination:
  plugin: entity:media
  default_bundle: image

migration_dependencies:
  optional:
    - migrate_files

Puntos clave

  • La reutilización de Media es crítica: una imagen = una entidad Media
  • entity_lookup verifica si ya existe un Media con el mismo nombre
  • migration_lookup obtiene el fid de la migración anterior
  • default_bundle está configurado como image

Este enfoque previene entidades media duplicadas cuando la misma imagen aparece múltiples veces en el CSV.

3. Migrando contenido y referenciando Media

Finalmente, migramos el contenido (nodos) y referenciamos las entidades Media.

Archivo de migración: migrate_plus.migration.products.yml

id: products
label: Import products

source:
  plugin: csv
  path: modules/custom/custom_migrate/data/products.csv
  delimiter: ','
  enclosure: '"'
  header_offset: 0
  ids:
    - code
  fields:
    0:
      name: cat
      label: 'Category'
    1:
      name: code
      label: 'Product code'
    2:
      name: title
      label: 'Title'
    3:
      name: image
      label: 'Image'

process:
  field_cat:
    plugin: entity_lookup
    entity_type: taxonomy_term
    bundle: cat_producto
    value_key: name
    source: cat
    ignore_case: true

  field_producto_codigo: code

  title:
    - plugin: callback
      callable: mb_strtolower
      source: title
    - plugin: callback
      callable: ucfirst

  type:
    plugin: default_value
    default_value: producto

  field_imagen/target_id:
    plugin: entity_lookup
    entity_type: media
    bundle: image
    value_key: name
    source: image
    ignore_case: true
    access_check: false

destination:
  plugin: entity:node

migration_dependencies:
  optional:
    - migrate_files
    - media_images

Puntos clave

  • Las entidades Media se referencian usando entity_lookup
  • La búsqueda se hace por el nombre del media (nombre del archivo de imagen)
  • Esto mantiene las migraciones de contenido limpias e independientes

Registrando migraciones automáticamente

Usando config_devel, podemos auto-instalar migraciones declarándolas en el .info.yml del módulo:

config_devel:
  install:
    - migrate_plus.migration.migrate_files
    - migrate_plus.migration.media_images
    - migrate_plus.migration.products

Ejecutando las migraciones

Recarga la configuración de migración:

drush cdi custom_migrate

Ejecuta las migraciones en orden:

drush mim migrate_files

drush mim media_images

drush mim products

Resultado final

  • Los archivos se copian y registran
  • Las entidades Media se crean y reutilizan
  • Los nodos referencian Media correctamente

Este enfoque es estable, reutilizable y preparado para el futuro en proyectos Drupal 10 y Drupal 11, y funciona igualmente bien con migraciones CSV, SQL o de Drupal a Drupal.

CA

Carlos Rincón

developer

Recent Posts