diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal7-file.php b/core/modules/migrate_drupal/tests/fixtures/drupal7-file.php
new file mode 100644
index 0000000000..a42246b0cb
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal7-file.php
@@ -0,0 +1,286 @@
+<?php
+// @codingStandardsIgnoreFile
+/**
+ * @file
+ * A database agnostic dump for testing purposes.
+ *
+ * This file was generated by the Drupal 8.0 db-tools.php script.
+ */
+
+use Drupal\Core\Database\Database;
+
+$connection = Database::getConnection();
+
+$connection->schema()->createTable('file_managed', array(
+  'fields' => array(
+    'fid' => array(
+      'type' => 'serial',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'unsigned' => TRUE,
+    ),
+    'uid' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+      'unsigned' => TRUE,
+    ),
+    'filename' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ),
+    'uri' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ),
+    'filemime' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ),
+    'filesize' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+      'unsigned' => TRUE,
+    ),
+    'status' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ),
+    'timestamp' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+      'unsigned' => TRUE,
+    ),
+  ),
+  'primary key' => array(
+    'fid',
+  ),
+  'mysql_character_set' => 'utf8',
+));
+
+$connection->insert('file_managed')
+->fields(array(
+  'fid',
+  'uid',
+  'filename',
+  'uri',
+  'filemime',
+  'filesize',
+  'status',
+  'timestamp',
+))
+->values(array(
+  'fid' => '1',
+  'uid' => '1',
+  'filename' => 'cube.jpeg',
+  'uri' => 'public://cube.jpeg',
+  'filemime' => 'image/jpeg',
+  'filesize' => '3620',
+  'status' => '1',
+  'timestamp' => '1421727515',
+))
+->values(array(
+  'fid' => '2',
+  'uid' => '1',
+  'filename' => 'ds9.txt',
+  'uri' => 'public://ds9.txt',
+  'filemime' => 'text/plain',
+  'filesize' => '4720',
+  'status' => '1',
+  'timestamp' => '1421727516',
+))
+->values(array(
+  'fid' => '3',
+  'uid' => '1',
+  'filename' => 'Babylon5.txt',
+  'uri' => 'private://Babylon5.txt',
+  'filemime' => 'text/plain',
+  'filesize' => '4',
+  'status' => '1',
+  'timestamp' => '1486104045',
+))
+->values(array(
+  'fid' => '4',
+  'uid' => '1',
+  'filename' => 'TerokNor.txt',
+  'uri' => 'temporary://TerokNor.txt',
+  'filemime' => 'text/plain',
+  'filesize' => '2369',
+  'status' => '1',
+  'timestamp' => '1421747516',
+))
+->execute();
+
+$connection->schema()->createTable('system', array(
+  'fields' => array(
+    'filename' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ),
+    'name' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ),
+    'type' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '12',
+      'default' => '',
+    ),
+    'owner' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ),
+    'status' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ),
+    'bootstrap' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ),
+    'schema_version' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '-1',
+    ),
+    'weight' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ),
+    'info' => array(
+      'type' => 'blob',
+      'not null' => FALSE,
+      'size' => 'normal',
+    ),
+  ),
+  'primary key' => array(
+    'filename',
+  ),
+  'mysql_character_set' => 'utf8',
+));
+
+$connection->insert('system')
+->fields(array(
+  'filename',
+  'name',
+  'type',
+  'owner',
+  'status',
+  'bootstrap',
+  'schema_version',
+  'weight',
+  'info',
+))
+->values(array(
+  'filename' => 'modules/file/file.module',
+  'name' => 'file',
+  'type' => 'module',
+  'owner' => '',
+  'status' => '1',
+  'bootstrap' => '0',
+  'schema_version' => '0',
+  'weight' => '0',
+  'info' => 'a:14:{s:4:"name";s:4:"File";s:11:"description";s:26:"Defines a file field type.";s:7:"package";s:4:"Core";s:7:"version";s:4:"7.40";s:4:"core";s:3:"7.x";s:12:"dependencies";a:1:{i:0;s:5:"field";}s:5:"files";a:1:{i:0;s:15:"tests/file.test";}s:7:"project";s:6:"drupal";s:9:"datestamp";s:10:"1444866674";s:5:"mtime";i:1444866674;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;s:8:"required";b:1;s:11:"explanation";s:73:"Field type(s) in use - see <a href="/admin/reports/fields">Field list</a>";}',
+))
+->values(array(
+  'filename' => 'modules/system/system.module',
+  'name' => 'system',
+  'type' => 'module',
+  'owner' => '',
+  'status' => '1',
+  'bootstrap' => '1',
+  'schema_version' => '7080',
+  'weight' => '0',
+  'info' => 'a:14:{s:4:"name";s:6:"System";s:11:"description";s:54:"Handles general site configuration for administrators.";s:7:"package";s:4:"Core";s:7:"version";s:4:"7.40";s:4:"core";s:3:"7.x";s:5:"files";a:6:{i:0;s:19:"system.archiver.inc";i:1;s:15:"system.mail.inc";i:2;s:16:"system.queue.inc";i:3;s:14:"system.tar.inc";i:4;s:18:"system.updater.inc";i:5;s:11:"system.test";}s:8:"required";b:1;s:9:"configure";s:19:"admin/config/system";s:7:"project";s:6:"drupal";s:9:"datestamp";s:10:"1444866674";s:5:"mtime";i:1444866674;s:12:"dependencies";a:0:{}s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}',
+))
+->execute();
+
+$connection->schema()->createTable('variable', array(
+  'fields' => array(
+    'name' => array(
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '128',
+      'default' => '',
+    ),
+    'value' => array(
+      'type' => 'blob',
+      'not null' => TRUE,
+      'size' => 'normal',
+    ),
+  ),
+  'primary key' => array(
+    'name',
+  ),
+  'mysql_character_set' => 'utf8',
+));
+
+$connection->insert('variable')
+->fields(array(
+  'name',
+  'value',
+))
+->values(array(
+  'name' => 'actions_max_stack',
+  'value' => 'i:28;',
+))
+->values(array(
+  'name' => 'file_default_scheme',
+  'value' => 's:6:"public";',
+))
+->values(array(
+  'name' => 'file_description_length',
+  'value' => 'i:256;',
+))
+->values(array(
+  'name' => 'file_description_type',
+  'value' => 's:9:"textfield";',
+))
+->values(array(
+  'name' => 'file_directory_path',
+  'value' => 's:19:"sites/default/files";',
+))
+->values(array(
+  'name' => 'file_icon_directory',
+  'value' => 's:25:"sites/default/files/icons";',
+))
+->values(array(
+  'name' => 'file_private_path',
+  'value' => 's:21:"sites/default/private";',
+))
+->values(array(
+  'name' => 'file_public_path',
+  'value' => 's:19:"sites/default/files";',
+))
+->values(array(
+  'name' => 'file_temporary_path',
+  'value' => 's:4:"/tmp";',
+))
+->execute();
diff --git a/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php b/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php
index c9c19a5c30..09a7fc6145 100644
--- a/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php
+++ b/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php
@@ -114,10 +114,13 @@ public static function run($initial_ids, $config, &$context) {
     // @todo Find a way to avoid this in https://www.drupal.org/node/2804611.
     if ($definition['destination']['plugin'] === 'entity:file') {
       // Make sure we have a single trailing slash.
-      if ($definition['source']['plugin'] === 'd7_file_private') {
+      $configuration['source']['constants']['source_base_path'] = rtrim($config['source_base_path'], '/') . '/';
+      // Use the private file path if the scheme property is set in the source
+      // plugin definition and is 'private'.
+      $scheme = $definition['source']['scheme'] ?? NULL;
+      if ($scheme === 'private') {
         $configuration['source']['constants']['source_base_path'] = rtrim($config['source_private_file_path'], '/') . '/';
       }
-      $configuration['source']['constants']['source_base_path'] = rtrim($config['source_base_path'], '/') . '/';
     }
 
     /** @var \Drupal\migrate\Plugin\Migration $migration */
diff --git a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php
index 705aa24f9a..bb741af5c0 100644
--- a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php
@@ -262,6 +262,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
     $config['source_base_path'] = $this->store->get('source_base_path');
+    $config['source_private_file_path'] = $this->store->get('source_private_file_path');
     $batch = [
       'title' => $this->t('Running upgrade'),
       'progress_message' => '',
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
index 5eb14ccdd5..798dabace6 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
@@ -69,6 +69,7 @@ public function testMigrateUpgradeExecute() {
     }
     else {
       $edit['source_base_path'] = $this->getSourceBasePath();
+      $edit['source_private_file_path'] = $this->getSourcePrivateFilePath();
     }
     if (count($drivers) !== 1) {
       $edit['driver'] = $driver;
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
index 4b6754487c..75e1b2d785 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
@@ -260,4 +260,22 @@ protected function assertMigrationResults(array $expected_counts, $version) {
     }
   }
 
+  /**
+   * Checks public and private files are copied but not temporary files.
+   */
+  protected function assertFileMigrations() {
+    $fs = \Drupal::service('file_system');
+    $files = $this->getManagedFiles();
+    foreach ($files as $file) {
+      $scheme = preg_replace('/:.*/', '', $file['uri']);
+      $filepath = $fs->realpath($file['uri']);
+      if ($scheme === 'temporary') {
+        $this->assertFileNotExists($filepath);
+      }
+      else {
+        $this->assertFileExists($filepath);
+      }
+    }
+  }
+
 }
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php
new file mode 100644
index 0000000000..8ece9e680a
--- /dev/null
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/FilePathTest.php
@@ -0,0 +1,308 @@
+<?php
+
+namespace Drupal\Tests\migrate_drupal_ui\Functional\d7;
+
+use Drupal\Core\File\FileSystemInterface;
+use Drupal\migrate\MigrateException;
+use Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeTestBase;
+
+/**
+ * Tests the Drupal 7 public and private file migrations.
+ *
+ * @group migrate_drupal_ui
+ */
+class FilePathTest extends MigrateUpgradeTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $profile = 'testing';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * The file system.
+   *
+   * @var \Drupal\Core\File\FileSystem
+   */
+  protected $fs;
+
+  /**
+   * The file path variables in the source database.
+   *
+   * @var string[]
+   */
+  protected $basePath = [];
+
+  /**
+   * The file path variables in the source database.
+   *
+   * @var string[]
+   */
+  protected $variable = [];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'file',
+    'migrate',
+    'migrate_drupal',
+    'migrate_drupal_ui',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->fs = \Drupal::service('file_system');
+    $this->loadFixture(drupal_get_path('module', 'migrate_drupal') . '/tests/fixtures/drupal7.php');
+  }
+
+  /**
+   * Executes all steps of migrations upgrade.
+   *
+   * @param string $file_private_path
+   *   The source database file_private_path value.
+   * @param string $file_public_path
+   *   The source database file_public_path value.
+   * @param string $file_temporary_path
+   *   The source database file_temporary_path value.
+   * @param string $private
+   *   The path to the source private files.
+   * @param string $public
+   *   The path to the source public files.
+   * @param string $temporary
+   *   The path to the source temporary files.
+   *
+   * @throws \Drupal\migrate\MigrateException
+   *
+   * @dataProvider providerTestFilePath
+   */
+  public function testFilePath($file_private_path, $file_public_path, $file_temporary_path, $private, $public, $temporary) {
+    $this->variable['private'] = $file_private_path;
+    $this->variable['public'] = $file_public_path;
+    $this->variable['temporary'] = $file_temporary_path;
+
+    $this->basePath['private'] = $private;
+    $this->basePath['public'] = $public;
+    $this->basePath['temporary'] = $temporary;
+
+    // Create the source files.
+    $this->makeFiles();
+
+    // Set the source db variables.
+    $this->sourceDatabase->update('variable')
+      ->fields(['value' => serialize($file_private_path)])
+      ->condition('name', 'file_private_path')
+      ->execute();
+    $this->sourceDatabase->update('variable')
+      ->fields(['value' => serialize($file_public_path)])
+      ->condition('name', 'file_public_path')
+      ->execute();
+    $this->sourceDatabase->update('variable')
+      ->fields(['value' => serialize($file_temporary_path)])
+      ->condition('name', 'file_temporary_path')
+      ->execute();
+
+    $connection_options = $this->sourceDatabase->getConnectionOptions();
+    $driver = $connection_options['driver'];
+    $connection_options['prefix'] = $connection_options['prefix']['default'];
+
+    // Use the driver connection form to get the correct options out of the
+    // database settings. This supports all of the databases we test against.
+    $drivers = drupal_get_database_types();
+    $form = $drivers[$driver]->getFormOptions($connection_options);
+    $connection_options = array_intersect_key($connection_options, $form + $form['advanced_options']);
+    $edit = [
+      $driver => $connection_options,
+      'version' => '7',
+    ];
+    if (count($drivers) !== 1) {
+      $edit['driver'] = $driver;
+    }
+    // Set the public and private base paths for the Credential Form.
+    $edit['source_private_file_path'] = $this->fs->realpath($this->getSourcePath('private'));
+    $edit['source_base_path'] = $this->fs->realpath($this->getSourcePath('public'));
+    $edits = $this->translatePostValues($edit);
+
+    // Start the upgrade.
+    $this->drupalGet('/upgrade');
+    $this->drupalPostForm(NULL, [], 'Continue');
+    $this->drupalPostForm(NULL, $edits, 'Review upgrade');
+
+    // The migrations are now in store - remove all but the file migrations.
+    $tempstore_private = \Drupal::service('tempstore.private');
+    $store = $tempstore_private->get('migrate_drupal_ui');
+    $all_migrations = $store->get('migrations');
+    $migration_array = array_intersect_key($all_migrations, [
+      'd7_file' => [],
+      'd7_file_private' => [],
+    ]);
+    $store->set('migrations', $migration_array);
+
+    // Perform the migrations.
+    $this->drupalPostForm(NULL, [], 'Perform upgrade');
+    $this->resetAll();
+    $this->assertFileMigrations();
+  }
+
+  /**
+   * Data provider of test dates for file path test.
+   *
+   * @return string[][]
+   *   An array of test data.
+   */
+  public function providerTestFilePath() {
+    return [
+      [
+        'file_private_path' => 'sites/default/private',
+        'file_public_path' => 'sites/default/files',
+        'file_temporary_path' => '/tmp',
+        'private' => '',
+        'public' => '',
+        'temporary' => '',
+      ],
+      [
+        'file_private_path' => 'sites/default/private',
+        'file_public_path' => 'sites/default/files',
+        'file_temporary_path' => '/tmp',
+        'private' => 'abc',
+        'public' => '',
+        'temporary' => '',
+      ],
+      [
+        'file_private_path' => 'sites/default/private',
+        'file_public_path' => 'sites/default/files',
+        'file_temporary_path' => '/tmp',
+        'private' => '',
+        'public' => 'def',
+        'temporary' => '',
+      ],
+      [
+        'file_private_path' => 'private',
+        'file_public_path' => 'files',
+        'file_temporary_path' => '/tmp',
+        'private' => 'abc',
+        'public' => 'def',
+        'temporary' => 'xyz',
+      ],
+    ];
+  }
+
+  /**
+   * Creates files for the test.
+   *
+   * The source files are written to a subdirectory of the temporary files
+   * directory of the test sites. The subdirectory path always ends with the
+   * path to the relevant scheme as set in the source variable table.
+   */
+  protected function makeFiles() {
+    // Get file information from the source database.
+    $files = $this->getManagedFiles();
+    foreach ($files as $file) {
+      $scheme = preg_replace('/:.*/', '', $file['uri']);
+
+      $path = isset($this->variable[$scheme]) ? $this->variable[$scheme] : '';
+      $base_path = $this->getSourcePath($scheme) . '/' . $path;
+      $filepath = $base_path . '/' . $file['filename'];
+      // Create the file.
+      $source_file = @fopen($filepath, 'w');
+      if (!$source_file) {
+        // If fopen didn't work, make sure there's a writable directory in
+        // place.
+        $this->fs = \Drupal::service('file_system');
+        $dir = $this->fs->dirname($filepath);
+        if (!$this->fs->prepareDirectory($dir, FileSystemInterface:: CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS)) {
+          throw new MigrateException("Could not create or write to directory '$dir'");
+        }
+        // Let's try that fopen again.
+        $source_file = @fopen($filepath, 'w');
+        if (!$source_file) {
+          throw new MigrateException("Could not write to file '$filepath'");
+        }
+      }
+      fwrite($source_file, '42');
+    }
+  }
+
+  /**
+   * Gets the source base path for the Credential form.
+   *
+   * @param string $scheme
+   *   The file scheme.
+   */
+  public function getSourcePath($scheme) {
+    $base_path = isset($this->basePath[$scheme]) ? $this->basePath[$scheme] : '';
+    // Puts the source files in the site temp directory.
+    return $this->tempFilesDirectory . '/' . $base_path;
+  }
+
+  /**
+   * Gets the file data.
+   *
+   * @return string[][]
+   *   Data from the source file_managed table.
+   */
+  public function getManagedFiles() {
+    return [
+      [
+        'filename' => 'cube.jpeg',
+        'uri' => 'public://cube.jpeg',
+      ],
+      [
+        'filename' => 'ds9.txt',
+        'uri' => 'public://ds9.txt',
+      ],
+      [
+        'filename' => 'Babylon5.txt',
+        'uri' => 'private://Babylon5.txt',
+      ],
+      [
+        'filename' => 'TerokNor.txt',
+        'uri' => 'temporary://TerokNor.txt',
+      ],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityCounts() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityCountsIncremental() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getAvailablePaths() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getMissingPaths() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSourceBasePath() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSourcePrivateFilePath() {
+  }
+
+}
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
index 373ddd8efb..4191814409 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
@@ -67,6 +67,24 @@ protected function getSourceBasePath() {
     return __DIR__ . '/files';
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSourcePrivateFilePath() {
+    return __DIR__ . '/files';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getFilenames() {
+    return [
+      'public' => ['cube.jpeg', 'ds9.txt'],
+      'private' => ['Babylon5.txt'],
+      'temporary' => ['TerokNor.txt'],
+    ];
+  }
+
   /**
    * {@inheritdoc}
    */
