Migrating the Media Library from one site to another

At the last WP Meetup Potsdam, which was a casual meeting for some food, drinks and talks, one of the new attendees asked a question that sounded easy, but for which we had different answers:

How can I migrate all images from one WordPress site to another site?

Different attendees came up with different solutions. Here are the ones that were mentioned.

Migrate the images using FTP

Many people working with websites use FTP to upload/download files to a server. So why not just download them from the source site and upload them into the wp-content/uploads folder of the new site.

Anyone knowing how WordPress deals with attachments (images and other files) probably knows, that not only the files must be there, but also an entry in the database. Otherwise, the images could only be hot linked using their URLs, but are not available in the media library.

Import files from a folder using a plugin

To import those files into the media library, you have to use plugins like Add From Server, which some of you might know. It hasn’t been updated for 3 years, but might still work, although the plugin description states, that it is not designed for migrations. I’ve found Media Sync as an actively maintained plugin, but I have never tested it myself.

Import media files using the WP-CLI

You can also use the WP-CLI to import media files from a folder. Here is an example importing files from one WordPress installation into another on the same server:

$ wp media import ../source/wp-content/uploads/**\/**\/*.jpg
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-1024x683.jpg' as attachment ID 6.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-150x150.jpg' as attachment ID 7.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-1536x1024.jpg' as attachment ID 8.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-2048x1365.jpg' as attachment ID 9.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-300x200.jpg' as attachment ID 10.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-768x512.jpg' as attachment ID 11.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391.jpg' as attachment ID 12.
Imported file '../source/wp-content/uploads/2023/08/28164a88367399c18.97744391-scaled.jpg' as attachment ID 13.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-1024x683.jpg' as attachment ID 14.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-150x150.jpg' as attachment ID 15.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-1536x1024.jpg' as attachment ID 16.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-2048x1365.jpg' as attachment ID 17.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-300x200.jpg' as attachment ID 18.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-768x512.jpg' as attachment ID 19.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317.jpg' as attachment ID 20.
Imported file '../source/wp-content/uploads/2023/08/41864a882e698f3d6.67081317-scaled.jpg' as attachment ID 21.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-1024x683.jpg' as attachment ID 22.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-150x150.jpg' as attachment ID 23.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-1536x1024.jpg' as attachment ID 24.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-2048x1365.jpg' as attachment ID 25.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-300x200.jpg' as attachment ID 26.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-768x512.jpg' as attachment ID 27.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907.jpg' as attachment ID 28.
Imported file '../source/wp-content/uploads/2023/08/75364a8821590f529.41962907-scaled.jpg' as attachment ID 29.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-1024x683.jpg' as attachment ID 30.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-150x150.jpg' as attachment ID 31.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-1536x1024.jpg' as attachment ID 32.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-2048x1365.jpg' as attachment ID 33.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-300x200.jpg' as attachment ID 34.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-768x512.jpg' as attachment ID 35.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704.jpg' as attachment ID 36.
Imported file '../source/wp-content/uploads/2023/08/89264a87feebb12a4.11887704-scaled.jpg' as attachment ID 37.
Success: Imported 32 of 32 items.

This example imports all *.jpg files in any monthly uploads subfolder. But you can also see one big issue here. Since WordPress creates many different file sizes of the original image, you would import all of them as separate media library items. So before importing any files you have copied over using FTP, you would have to manually remove them. When you migrate large media libraries, that task can take a while and you might make mistakes. So what to use instead? There are other (premium) plugins to migrate files, but there is a simpler and free way.

Migrating the media library with the WordPress Export/Import

Any WordPress installation comes with a default “Export” mechanism. You can find it at “Tools > Export” in your dashboard. Here, you can select which post types you want to export and optionally filter by a date range.

Export the media items

We want to export only media files, and we don’t select a date range, so all items will be exported:

The export tool configured to export all media items.
The export tool configured to export all media items

After clicking the “Download Export File”, your browser will ask you to save an XML file. This file can be used on your target site to import the media. So the export tool does not export all images (or other media file types), but only a file with the information where to find them.

Import the media items

Now you access the dashboard of the target site. Here you navigate to “Tools > Import”. At the bottom, you should see the “WordPress” importer. It is not installed by default, but you can install the plugin easily using the link:

The overview of the import tools, with the "Install Now" link highlighted.
The overview of the import tools, with the “Install Now” link highlighted

This will install and activate the plugin. The link will then change to “Run importer”. This brings you to a page with a file upload. Select the previously downloaded XML file and hit the “Upload file and import” button on that page. You should then see a page like this:

Step 2 of the XML import, that ask you to assign authors and gives you the option to "Import Attachments".
Step 2 of the XML import, that ask you to assign authors and gives you the option to “Import Attachments”

This page will list each author from the source site and asks you if you want to import them by creating a user or by assigning the contents of this user to an existing user.

The most important part is the checkout to “Download and import file attachments”. This checkout must be active. Then you click the “Submit” button and the import begins. Depending on the number of files, this might take a while.

Potential script timeout

As this process will download all files from your source site via HTTP and saves them to your new site (while also creating all the other images sizes), it might happen, that the request times out. You can then either import the same XML file again (existing content will be skipped), or you might have to split up the exported XML file into multiple ones, where you select a date range that is small enough.

Conclusion

There are many ways to migrate media files from one site to another. While I really like to use the WP-CLI for this task, the WordPress Export/Import has some major advantages. All you need it the ability to install the importer plugin. No need to use FTP and SSH to install and run the WP-CLI on the target site (which you might not have permissions to). You can also filter the media items by date and if you know how to edit XML files, you can also adjust what should be imported.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

Leave a Reply

Your email address will not be published. Required fields are marked *