Com migrar fitxers i imatges amb Drupal a un camp Media

Client
  • Omitsis
Technologies
Date
  • 11/01/2026

Quan migrem contingut a Drupal des d’una altra font (CSV, Drupal 7, sistemes externs, etc.), és molt comú treballar amb imatges i fitxers. Des de Drupal 8 i especialment a Drupal 9–11, les entitats Media són la forma recomanada de gestionar imatges i fitxers en lloc d’utilitzar camps d’imatge/fitxer directament.

Aquest article explica com migrar imatges a entitats Media utilitzant Migrate, pas a pas, i després referenciar aquestes entitats Media des del contingut. Els exemples estan basats en una font CSV, però els mateixos conceptes s’apliquen a altres fonts.

Per què utilitzar Media en lloc de camps file/image?

El mòdul Media ha estat al nucli de Drupal durant anys i és madur i estable a Drupal 10 i Drupal 11. Utilitzar entitats Media t’ofereix:

  • Imatges i fitxers reutilitzables entre continguts
  • Una biblioteca de mitjans centralitzada
  • Camps addicionals als mitjans (copyright, autor, alt per defecte, etc.)
  • Millor experiència editorial

A Omitsis, utilitzar Media és ara, i des de fa anys, un estàndard per defecte per a projectes Drupal.

El desavantatge és que migrar a Media és lleugerament més complex que migrar directament a camps file. Aquest article se centra a resoldre això.

Prerequisits

Aquest article assumeix coneixements bàsics de l’API de Migrate.

Si ets nou en migracions, es recomana llegir primer una introducció sobre migració des de CSV utilitzant el mòdul Migrate.

No utilitzarem helpers de contrib com migrate_files_to_media. En el seu lloc, ens basarem únicament en plugins de migrate del core/contrib perquè entenguis completament què està passant.

Mòduls requerits (Drupal 10 / 11)

Instal·la els mòduls requerits via Composer:

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

Habilita’ls:

drush en -y migrate migrate_plus migrate_tools migrate_source_csv config_devel

config_devel és opcional però molt convenient durant el desenvolupament per auto-instal·lar fitxers YAML de migració.

Resum de l’estratègia de migració

Dividirem el procés en tres migracions:

  1. Migració de fitxers – copiar fitxers d’imatge a Drupal i crear entitats file
  2. Migració de Media – crear entitats media:image referenciant aquests fitxers
  3. Migració de contingut – crear nodes referenciant les entitats Media

Aquesta separació fa que les migracions siguin més fàcils de depurar, re-executar i reutilitzar.

1. Migrant fitxers d’imatge

Primer, migrem els fitxers físics d’imatge i creem entitats file.

Fitxer de migració: 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

Punts clau

  • Les constants defineixen els directoris d’origen i destí
  • file_copy copia la imatge i crea una entitat file
  • El CSV només conté el nom del fitxer d’imatge, no rutes completes
  • file_copy suporta opcions d’overwrite i reuse si és necessari

En aquest punt, Drupal coneix els fitxers, però encara no com a Media.

2. Creant entitats Media des de fitxers

Ara convertim els fitxers en entitats media:image.

Fitxer de migració: 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 entitats media duplicades
  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

Punts clau

  • La reutilització de Media és crítica: una imatge = una entitat Media
  • entity_lookup verifica si ja existeix un Media amb el mateix nom
  • migration_lookup obté el fid de la migració anterior
  • default_bundle està configurat com a image

Aquest enfocament prevé entitats media duplicades quan la mateixa imatge apareix múltiples vegades al CSV.

3. Migrant contingut i referenciant Media

Finalment, migrem el contingut (nodes) i referenciem les entitats Media.

Fitxer de migració: 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

Punts clau

  • Les entitats Media es referencien utilitzant entity_lookup
  • La cerca es fa pel nom del media (nom del fitxer d’imatge)
  • Això manté les migracions de contingut netes i independents

Registrant migracions automàticament

Utilitzant config_devel, podem auto-instal·lar migracions declarant-les al .info.yml del mòdul:

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

Executant les migracions

Recarrega la configuració de migració:

drush cdi custom_migrate

Executa les migracions en ordre:

drush mim migrate_files

drush mim media_images

drush mim products

Resultat final

  • Els fitxers es copien i registren
  • Les entitats Media es creen i reutilitzen
  • Els nodes referencien Media correctament

Aquest enfocament és estable, reutilitzable i preparat per al futur en projectes Drupal 10 i Drupal 11, i funciona igualment bé amb migracions CSV, SQL o de Drupal a Drupal.

CA

Carlos Rincón

developer

Recent Posts