Download Selected Media Files as a ZIP
Adds a "Download as ZIP" bulk action to the Media Library list view that packs the selected original files into one archive, handy for sending a batch of photos or documents to someone.
Opens WPIDE on
Code
// Largest total size to zip, in megabytes.
$wpide_zip_limit_mb = 200;
add_filter( 'bulk_actions-upload', function ( $actions ) {
if ( class_exists( 'ZipArchive' ) ) {
$actions['wpide_zip_media'] = 'Download as ZIP';
}
return $actions;
} );
add_filter( 'handle_bulk_actions-upload', function ( $redirect, $action, $ids ) use ( $wpide_zip_limit_mb ) {
if ( 'wpide_zip_media' !== $action || ! class_exists( 'ZipArchive' ) || ! current_user_can( 'upload_files' ) ) {
return $redirect;
}
$files = array();
$total = 0;
foreach ( $ids as $id ) {
$path = function_exists( 'wp_get_original_image_path' ) && wp_attachment_is_image( $id ) ? wp_get_original_image_path( $id ) : get_attached_file( $id );
if ( $path && is_readable( $path ) && current_user_can( 'read_post', $id ) ) {
$files[] = $path;
$total += filesize( $path );
}
}
if ( ! $files || $total > $wpide_zip_limit_mb * MB_IN_BYTES ) {
return add_query_arg( 'wpide_zip', $files ? 'too_big' : 'empty', $redirect );
}
if ( defined( 'WP_CLI' ) && WP_CLI ) {
return $redirect;
}
$zip_path = wp_tempnam( 'media.zip' );
$zip = new ZipArchive();
if ( true !== $zip->open( $zip_path, ZipArchive::OVERWRITE ) ) {
return add_query_arg( 'wpide_zip', 'failed', $redirect );
}
$used = array();
foreach ( $files as $path ) {
$name = wp_basename( $path );
// Avoid collisions between files with the same name in different months.
$name = isset( $used[ $name ] ) ? pathinfo( $name, PATHINFO_FILENAME ) . '-' . count( $used ) . '.' . pathinfo( $name, PATHINFO_EXTENSION ) : $name;
$used[ $name ] = true;
$zip->addFile( $path, $name );
}
$zip->close();
nocache_headers();
header( 'Content-Type: application/zip' );
header( 'Content-Disposition: attachment; filename=media-' . gmdate( 'Y-m-d' ) . '.zip' );
header( 'Content-Length: ' . filesize( $zip_path ) );
readfile( $zip_path );
wp_delete_file( $zip_path );
exit;
}, 10, 3 );
add_action( 'admin_notices', function () use ( $wpide_zip_limit_mb ) {
if ( empty( $_GET['wpide_zip'] ) ) {
return;
}
$messages = array(
'too_big' => sprintf( 'The selected files are larger than %d MB. Select fewer files.', $wpide_zip_limit_mb ),
'empty' => 'None of the selected files could be read.',
'failed' => 'The ZIP file could not be created.',
);
$key = sanitize_key( $_GET['wpide_zip'] );
if ( isset( $messages[ $key ] ) ) {
printf( '<div class="notice notice-error is-dismissible"><p>%s</p></div>', esc_html( $messages[ $key ] ) );
}
} );
Notes
Needs the PHP Zip extension; limited to 200 MB of files per download to protect the server.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.