Exporting / downloading your WordPress media library can be quick and hassle-free. This guide shows how to download all uploaded images as a single ZIP file without extra folders.
A setting for Export Media Library has been added into the Tools submenu as can be seen in this screenshot.

The following code can be added to any Code Snippet plugin as a PHP function.
// Export Media Library - Flat ZIP, originals only, auto-delete after download
add_action('admin_menu', function() {
add_submenu_page(
'tools.php',
'Export Media Library',
'Export Media Library',
'manage_options',
'export-media-library-flat',
'beml_admin_page_flat'
);
});
/**
* Handle secure ZIP download before any output
*/
add_action('admin_init', function() {
if (
is_admin() &&
isset($_GET['page']) &&
$_GET['page'] === 'export-media-library-flat' &&
isset($_GET['beml_download'])
) {
$zipfile = get_option('beml_zipfile', '');
if ($zipfile && file_exists($zipfile)) {
// Clear any previous output
while (ob_get_level()) {
ob_end_clean();
}
// Force download headers
nocache_headers();
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($zipfile) . '"');
header('Content-Length: ' . filesize($zipfile));
flush();
// Send file
readfile($zipfile);
// Auto-delete after download
@unlink($zipfile);
delete_option('beml_zipfile');
delete_option('beml_status');
exit;
}
}
});
if (!function_exists('beml_admin_page_flat')) {
/**
* Render Export Media Library admin page
*/
function beml_admin_page_flat() {
// Current export status and ZIP path
$status = get_option('beml_status', '');
$zipfile = get_option('beml_zipfile', '');
// Handle export request
if (isset($_POST['beml_start_export']) && check_admin_referer('beml_export', 'beml_export_nonce')) {
global $wpdb;
// Reuse recent ZIP if <10 minutes old
if ($zipfile && file_exists($zipfile) && (time() - filemtime($zipfile) < 600)) {
$status = 'completed';
} else {
// Delete old ZIP if it exists
if (!empty($zipfile) && file_exists($zipfile)) {
@unlink($zipfile);
delete_option('beml_zipfile');
}
// Check ZipArchive availability
if (!class_exists('ZipArchive')) {
$status = 'error_ziparchive';
} else {
// Query all attachment IDs
$attachment_ids = $wpdb->get_col("
SELECT ID FROM $wpdb->posts
WHERE post_type='attachment'
AND post_status='inherit'
");
if ($attachment_ids) {
$sitename = sanitize_title(get_bloginfo('name'));
$zipname = $sitename . '-media-library-' . date('Y-m-d-H-i-s') . '.zip';
$upload_dir = wp_upload_dir();
$zip_path = $upload_dir['basedir'] . '/' . $zipname;
$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
// Add only original files
foreach ($attachment_ids as $att_id) {
$file = get_attached_file($att_id, true);
if ($file && file_exists($file)) {
$zip->addFile($file, basename($file));
}
}
$zip->close();
update_option('beml_status', 'completed');
update_option('beml_zipfile', $zip_path);
$status = 'completed';
$zipfile = $zip_path;
} else {
$status = 'error';
}
} else {
$status = 'empty';
}
}
}
}
?>
<div class="wrap">
<h1>Export Media Library</h1>
<?php if ($status === 'completed' && file_exists($zipfile)): ?>
<p>Status: Export completed!</p>
<a href="<?php echo esc_url(admin_url('tools.php?page=export-media-library-flat&beml_download=1')); ?>"
class="button button-primary">Download ZIP</a>
<form method="post" style="display:inline;">
<?php wp_nonce_field('beml_export', 'beml_export_nonce'); ?>
<input type="submit" name="beml_start_export" class="button" value="Start New Export">
</form>
<?php elseif ($status === 'empty'): ?>
<p>No media found in the library.</p>
<form method="post">
<?php wp_nonce_field('beml_export', 'beml_export_nonce'); ?>
<input type="submit" name="beml_start_export" class="button button-primary" value="Start Export">
</form>
<?php elseif ($status === 'error_ziparchive'): ?>
<p>Error: PHP ZipArchive extension is required.</p>
<?php elseif ($status === 'error'): ?>
<p>Error creating ZIP.</p>
<form method="post">
<?php wp_nonce_field('beml_export', 'beml_export_nonce'); ?>
<input type="submit" name="beml_start_export" class="button button-primary" value="Start Export">
</form>
<?php else: ?>
<p>Click "Start Export" to begin exporting your media library.</p>
<form method="post">
<?php wp_nonce_field('beml_export', 'beml_export_nonce'); ?>
<input type="submit" name="beml_start_export" class="button button-primary" value="Start Export">
</form>
<?php endif; ?>
</div>
<?php
}
}
Another tutorial on import and export of WordPress web site.







