diff --git a/core/modules/media/config/optional/system.action.media_delete_action.yml b/core/modules/media/config/optional/system.action.media_delete_action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7311917463850eb89006ae8dfd026c2534c85923
--- /dev/null
+++ b/core/modules/media/config/optional/system.action.media_delete_action.yml
@@ -0,0 +1,10 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - media
+id: media_delete_action
+label: 'Delete media'
+type: media
+plugin: entity:delete_action:media
+configuration: {  }
diff --git a/core/modules/media/config/optional/system.action.media_publish_action.yml b/core/modules/media/config/optional/system.action.media_publish_action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0e5cf4f75b4397e5ef1c8dc738419d82fb70605e
--- /dev/null
+++ b/core/modules/media/config/optional/system.action.media_publish_action.yml
@@ -0,0 +1,10 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - media
+id: media_publish_action
+label: 'Publish media'
+type: media
+plugin: entity:publish_action:media
+configuration: {  }
diff --git a/core/modules/media/config/optional/system.action.media_save_action.yml b/core/modules/media/config/optional/system.action.media_save_action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ead75740873d8835713bb9f6064b14311bb0acb5
--- /dev/null
+++ b/core/modules/media/config/optional/system.action.media_save_action.yml
@@ -0,0 +1,10 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - media
+id: media_save_action
+label: 'Save media'
+type: media
+plugin: entity:save_action:media
+configuration: {  }
diff --git a/core/modules/media/config/optional/system.action.media_unpublish_action.yml b/core/modules/media/config/optional/system.action.media_unpublish_action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2d24d73d5cda78bcdce28dda020f76a10dc687cc
--- /dev/null
+++ b/core/modules/media/config/optional/system.action.media_unpublish_action.yml
@@ -0,0 +1,10 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - media
+id: media_unpublish_action
+label: 'Unpublish media'
+type: media
+plugin: entity:unpublish_action:media
+configuration: {  }
diff --git a/core/modules/media/config/optional/views.view.media.yml b/core/modules/media/config/optional/views.view.media.yml
index 88b76745c8b3b5d63fdb8b1b3f787594ff550ffe..84587b5fb4876dcf0fc5d11b49d437172a32400c 100644
--- a/core/modules/media/config/optional/views.view.media.yml
+++ b/core/modules/media/config/optional/views.view.media.yml
@@ -132,6 +132,59 @@ display:
       row:
         type: fields
       fields:
+        media_bulk_form:
+          id: media_bulk_form
+          table: media
+          field: media_bulk_form
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          action_title: Action
+          include_exclude: exclude
+          selected_actions: {  }
+          entity_type: media
+          plugin_id: bulk_form
         thumbnail__target_id:
           id: thumbnail__target_id
           table: media_field_data
diff --git a/core/modules/media/media.routing.yml b/core/modules/media/media.routing.yml
index 9fbadeff29471a3640463653f4475122de0710ac..ea0858d4629802145d35091820a2f8e536265277 100644
--- a/core/modules/media/media.routing.yml
+++ b/core/modules/media/media.routing.yml
@@ -1,3 +1,8 @@
+# @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.0.
+#   This route is not used in Drupal core. As an internal API, it may also be
+#   removed in a minor release. If you are using it, copy the class
+#   and the related "entity.media.multiple_delete_confirm" route to your
+#   module.
 entity.media.multiple_delete_confirm:
   path: '/admin/content/media/delete'
   defaults:
diff --git a/core/modules/media/src/Entity/Media.php b/core/modules/media/src/Entity/Media.php
index 6e58771938840cf3d772b54f8f08b2fd66df76a3..cca42de3878bbd1c6836647f7527bc6f1d7b339f 100644
--- a/core/modules/media/src/Entity/Media.php
+++ b/core/modules/media/src/Entity/Media.php
@@ -38,6 +38,7 @@
  *       "add" = "Drupal\media\MediaForm",
  *       "edit" = "Drupal\media\MediaForm",
  *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
+ *       "delete-multiple-confirm" = "Drupal\Core\Entity\Form\DeleteMultipleForm",
  *     },
  *     "translation" = "Drupal\content_translation\ContentTranslationHandler",
  *     "views_data" = "Drupal\media\MediaViewsData",
@@ -76,6 +77,7 @@
  *     "canonical" = "/media/{media}",
  *     "collection" = "/admin/content/media",
  *     "delete-form" = "/media/{media}/delete",
+ *     "delete-multiple-form" = "/media/delete",
  *     "edit-form" = "/media/{media}/edit",
  *     "revision" = "/media/{media}/revisions/{media_revision}/view",
  *   }
diff --git a/core/modules/media/src/Form/MediaDeleteMultipleConfirmForm.php b/core/modules/media/src/Form/MediaDeleteMultipleConfirmForm.php
index 66598873f46d461cff0dfd0b1bdc85f72e013361..2d6850b7533163a4861143e1485e817f2e2ce148 100644
--- a/core/modules/media/src/Form/MediaDeleteMultipleConfirmForm.php
+++ b/core/modules/media/src/Form/MediaDeleteMultipleConfirmForm.php
@@ -13,6 +13,12 @@
 /**
  * Provides a confirmation form to delete multiple media items at once.
  *
+ * @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.0.
+ *   This route is not used in Drupal core. As an internal API, it may also be
+ *   removed in a minor release. If you are using it, copy the class
+ *   and the related "entity.media.multiple_delete_confirm" route to your
+ *   module.
+ *
  * @internal
  */
 class MediaDeleteMultipleConfirmForm extends ConfirmFormBase {
@@ -47,6 +53,7 @@ class MediaDeleteMultipleConfirmForm extends ConfirmFormBase {
    *   The entity type manager.
    */
   public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $manager) {
+    @trigger_error(__CLASS__ . ' is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. It is not used in Drupal core. As an internal API, it may also be removed in a minor release. If you are using it, copy the class and the related "entity.media.multiple_delete_confirm" route to your module.', E_USER_DEPRECATED);
     $this->tempStoreFactory = $temp_store_factory;
     $this->storage = $manager->getStorage('media');
   }
diff --git a/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml b/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2c212b8248a59225d4f5da14dfd226e01a91f69d
--- /dev/null
+++ b/core/modules/media/tests/modules/media_test_views/config/install/views.view.test_media_bulk_form.yml
@@ -0,0 +1,154 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - media
+    - user
+id: test_media_bulk_form
+label: ''
+module: views
+description: ''
+tag: ''
+base_table: media_field_data
+base_field: mid
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      style:
+        type: table
+      row:
+        type: fields
+      fields:
+        media_bulk_form:
+          id: media_bulk_form
+          table: media
+          field: media_bulk_form
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          action_title: 'With selection'
+          include_exclude: exclude
+          selected_actions: {  }
+          entity_type: media
+          plugin_id: bulk_form
+        name:
+          id: name
+          table: media_field_data
+          field: name
+          entity_type: media
+          entity_field: media
+          hide_empty: false
+          empty_zero: false
+          settings:
+            link_to_entity: false
+          plugin_id: field
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: 'Media name'
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+        status:
+          id: status
+          table: media_field_data
+          field: status
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: Status
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: boolean
+          settings:
+            format: custom
+            format_custom_true: Published
+            format_custom_false: Unpublished
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          entity_type: media
+          entity_field: status
+          plugin_id: field
+      sorts:
+        mid:
+          id: mid
+          table: media_field_data
+          field: mid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          order: ASC
+          exposed: false
+          expose:
+            label: ''
+          entity_type: media
+          entity_field: mid
+          plugin_id: standard
+      title: 'Entity bulk form test view'
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
+  page_1:
+    display_plugin: page
+    id: page_1
+    display_title: Page
+    position: 1
+    display_options:
+      path: test-media-bulk-form
diff --git a/core/modules/media/tests/src/Functional/MediaBulkFormTest.php b/core/modules/media/tests/src/Functional/MediaBulkFormTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..44ec6b8e16108d6ec17c26d6880fda7d43094f19
--- /dev/null
+++ b/core/modules/media/tests/src/Functional/MediaBulkFormTest.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace Drupal\Tests\media\Functional;
+
+use Drupal\media\Entity\Media;
+use Drupal\views\Views;
+
+/**
+ * Tests a media bulk form.
+ *
+ * @group media
+ */
+class MediaBulkFormTest extends MediaFunctionalTestBase {
+
+  /**
+   * Modules to be enabled.
+   *
+   * @var array
+   */
+  public static $modules = ['media_test_views'];
+
+  /**
+   * The test media type.
+   *
+   * @var \Drupal\media\MediaTypeInterface
+   */
+  protected $testMediaType;
+
+  /**
+   * The test media items.
+   *
+   * @var \Drupal\media\MediaInterface[]
+   */
+  protected $mediaItems;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->testMediaType = $this->createMediaType();
+
+    // Create some test media items.
+    $this->mediaItems = [];
+    for ($i = 1; $i <= 5; $i++) {
+      $media = Media::create([
+        'bundle' => $this->testMediaType->id(),
+      ]);
+      $media->save();
+      $this->mediaItems[] = $media;
+    }
+  }
+
+  /**
+   * Tests the media bulk form.
+   */
+  public function testBulkForm() {
+    $session = $this->getSession();
+    $page = $session->getPage();
+    $assert_session = $this->assertSession();
+
+    // Check that all created items are present in the test view.
+    $view = Views::getView('test_media_bulk_form');
+    $view->execute();
+    $this->assertEquals($view->total_rows, 5);
+
+    // Check the operations are accessible to the logged in user.
+    $this->drupalGet('test-media-bulk-form');
+    // Current available actions: Delete, Save, Publish, Unpublish.
+    $available_actions = [
+      'media_delete_action',
+      'media_publish_action',
+      'media_save_action',
+      'media_unpublish_action',
+    ];
+    foreach ($available_actions as $action_name) {
+      $assert_session->optionExists('action', $action_name);
+    }
+
+    // Test unpublishing in bulk.
+    $page->checkField('media_bulk_form[0]');
+    $page->checkField('media_bulk_form[1]');
+    $page->checkField('media_bulk_form[2]');
+    $page->selectFieldOption('action', 'media_unpublish_action');
+    $page->pressButton('Apply to selected items');
+    $assert_session->pageTextContains('Unpublish media was applied to 3 items');
+    $this->assertFalse($this->storage->loadUnchanged(1)->isPublished(), 'The unpublish action failed in some of the media items.');
+    $this->assertFalse($this->storage->loadUnchanged(2)->isPublished(), 'The unpublish action failed in some of the media items.');
+    $this->assertFalse($this->storage->loadUnchanged(3)->isPublished(), 'The unpublish action failed in some of the media items.');
+
+    // Test publishing in bulk.
+    $page->checkField('media_bulk_form[0]');
+    $page->checkField('media_bulk_form[1]');
+    $page->selectFieldOption('action', 'media_publish_action');
+    $page->pressButton('Apply to selected items');
+    $assert_session->pageTextContains('Publish media was applied to 2 items');
+    $this->assertTrue($this->storage->loadUnchanged(1)->isPublished(), 'The publish action failed in some of the media items.');
+    $this->assertTrue($this->storage->loadUnchanged(2)->isPublished(), 'The publish action failed in some of the media items.');
+
+    // Test deletion in bulk.
+    $page->checkField('media_bulk_form[0]');
+    $page->checkField('media_bulk_form[1]');
+    $page->selectFieldOption('action', 'media_delete_action');
+    $page->pressButton('Apply to selected items');
+    $assert_session->pageTextContains('Are you sure you want to delete these media items?');
+    $page->pressButton('Delete');
+    $assert_session->pageTextContains('Deleted 2 items.');
+    $this->assertNull($this->storage->loadUnchanged(1), 'Could not delete some of the media items.');
+    $this->assertNull($this->storage->loadUnchanged(2), 'Could not delete some of the media items.');
+  }
+
+}