Migrating Drupal 7 Image Files to Drupal 8 Media Images (no PHP required!)

I’m new to migrate. And it’s a beast. But I think after a few dozen hours of diligence, I think I’ve figured out my preferred method.

This post is for someone who already understands how to use views, develop custom modules, and knows how to use drush migration operations.

I originally tried using migrate_drupal, which honestly did a great job at migrating my user roles, users, and taxonomies. But the site I am migrating is 5 years old with a good amount of technical debt having been touched by over 10 (and maybe even 20) developers over its lifetime, so I think it’s time for a fresh start. I want to migrate everything else (content types, files, etc) manually.

All the Drupal 7 content types were using image (file) fields, but I want the new Drupal 8 site to use media fields. I couldn’t use the migration provided by migrate_drupal, so I had to get creative.

This will be a two step process:

  1. Use D7 views_datasource module to create JSON endpoints on my old site (and since we’re using a JSON source, you can honestly migrate from anything).
  2. Write a custom migration in D8.

Drupal 7 and Views JSON

Create a views JSON that pulls all file content with the following fields:

  • File ID (this will become the Media ID — we want to keep the IDs so when we merge content, it’ll be easier to also migrate their references)
  • Name
  • Absolute path (e.g. https://fullpath.com/sites/default/files/something.jpg)
  • Alt text
  • Date
  • User ID (Many users in CMS — I want to make sure they keep ownership of their images)
  • Title text (optional and not really used, but some people have taken the time to enter this field so I figure it would be worth migrating over)

Also, in the format settings, make sure you set a root object name (I used “images”) and leave the the “Top-level child object” field empty.


Now, your JSON object should look something like this:

The Drupal 8 Migration

Now for the beast. On your new site, install the following contrib modules:

  • media (core)
  • migrate (core)
  • migrate_plus (contrib)
  • migrate_tools (contrib)

You’ll also need to apply this patch that fixes a problem with the entity_generate plugin in order to get UIDs and FIDs to import correctly into your generated file entities https://www.drupal.org/project/migrate_plus/issues/2975266

You’ll then need two files in a custom module:

  • my_module/config/install/migrate_plus.migration_group.files.yml
  • my_module/config/install/migrate_plus.migration.images.yml

Next Steps

Install the your custom module, and you should be good to go with a drush mim images.

I’m going to use this to also migrate PDFs and other documents. I thought about creating one huge migration to migrate all file entities to all media entities, but I figure it would be cleaner (and more maintainable) to do one bundle at a time.

This took me longer than I’d like to admit to get together, but hopefully this works for you like it did for me. Feel free to drop a comment for any comments/questions. Good luck!