diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityFile.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityFile.php
index 77b471f..5678061 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/EntityFile.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityFile.php
@@ -9,10 +9,14 @@
 
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\File\FileSystemInterface;
+use Drupal\Core\StreamWrapper\LocalStream;
+use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
+use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\migrate\Entity\MigrationInterface;
-use Drupal\migrate\Plugin\MigratePluginManager;
 use Drupal\migrate\Row;
 use Drupal\migrate\MigrateException;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Every migration that uses this destination must have an optional
@@ -25,9 +29,19 @@
 class EntityFile extends EntityContentBase {
 
   /**
+   * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
+   */
+  protected $streamWrapperManager;
+
+  /**
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  protected $fileSystem;
+
+  /**
    * {@inheritdoc}
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, TranslationInterface $translator, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, StreamWrapperManagerInterface $stream_wrappers, FileSystemInterface $file_system) {
     $configuration += array(
       'source_base_path' => '',
       'source_path_property' => 'filepath',
@@ -36,6 +50,29 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
       'urlencode' => FALSE,
     );
     parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager);
+
+    $this->stringTranslation = $translator;
+    $this->streamWrapperManager = $stream_wrappers;
+    $this->fileSystem = $file_system;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
+    $entity_type = static::getEntityTypeId($plugin_id);
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('string_translation'),
+      $container->get('entity.manager')->getStorage($entity_type),
+      array_keys($container->get('entity.manager')->getBundleInfo($entity_type)),
+      $container->get('entity.manager'),
+      $container->get('stream_wrapper_manager'),
+      $container->get('file_system')
+    );
   }
 
   /**
@@ -44,52 +81,141 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
   public function import(Row $row, array $old_destination_id_values = array()) {
     $file = $row->getSourceProperty($this->configuration['source_path_property']);
     $destination = $row->getDestinationProperty($this->configuration['destination_path_property']);
+    $source = $this->configuration['source_base_path'] . $file;
 
-    // We check the destination to see if this is a temporary file. If it is
-    // then we do not prepend the source_base_path because temporary files are
-    // already absolute.
-    $source = $this->isTempFile($destination) ? $file : $this->configuration['source_base_path'] . $file;
-
-    $dirname = drupal_dirname($destination);
-    if (!file_prepare_directory($dirname, FILE_CREATE_DIRECTORY)) {
-      throw new MigrateException(t('Could not create directory %dirname', array('%dirname' => $dirname)));
+    // Ensure the source file exists, if it's a local URI or path.
+    if ($this->isLocalUri($source) && !file_exists($source)) {
+      throw new MigrateException($this->t('File %source does not exist.', ['%source' => $source]));
     }
 
     // If the start and end file is exactly the same, there is nothing to do.
-    if (drupal_realpath($source) === drupal_realpath($destination)) {
+    if ($this->isLocationUnchanged($source, $destination)) {
       return parent::import($row, $old_destination_id_values);
     }
 
-    $replace = FILE_EXISTS_REPLACE;
-    if (!empty($this->configuration['rename'])) {
-      $entity_id = $row->getDestinationProperty($this->getKey('id'));
-      if (!empty($entity_id) && ($entity = $this->storage->load($entity_id))) {
-        $replace = FILE_EXISTS_RENAME;
+    $replace = $this->getOverwriteMode($row);
+    $success = $this->writeFile($source, $destination, $replace);
+    if (empty($success)) {
+      $dir = $this->getDirectory($destination);
+      if (file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
+        $success = $this->writeFile($source, $destination, $replace);
+      }
+      else {
+        throw new MigrateException($this->t('Could not create directory %dir', ['%dir' => $dir]));
       }
     }
 
+    if ($success) {
+      return parent::import($row, $old_destination_id_values);
+    }
+    else {
+      throw new MigrateException($this->t('File %source could not be copied to %destination.', ['%source' => $source, '%destination' => $destination]));
+    }
+  }
+
+  /**
+   * Tries to move or copy a file.
+   *
+   * @param string $source
+   *  The source path or URI.
+   * @param string $destination
+   *  The destination path or URI.
+   * @param integer $replace
+   *  FILE_EXISTS_REPLACE (default) or FILE_EXISTS_RENAME.
+   *
+   * @return boolean
+   *  TRUE on success, FALSE on failure.
+   */
+  protected function writeFile($source, $destination, $replace = FILE_EXISTS_REPLACE) {
     if ($this->configuration['move']) {
-      $copied = file_unmanaged_move($source, $destination, $replace);
+      return (boolean) file_unmanaged_move($source, $destination, $replace);
     }
     else {
-      // Determine whether we can perform this operation based on overwrite rules.
-      $original_destination = $destination;
       $destination = file_destination($destination, $replace);
-      if ($destination === FALSE) {
-        throw new MigrateException(t('File %file could not be copied because a file by that name already exists in the destination directory (%destination)', array('%file' => $source, '%destination' => $original_destination)));
-      }
       $source = $this->urlencode($source);
-      $copied = @copy($source, $destination);
+      return @copy($source, $destination);
     }
-    if ($copied) {
-      return parent::import($row, $old_destination_id_values);
+  }
+
+  /**
+   * Determines how to handle file conflicts.
+   *
+   * @param \Drupal\migrate\Row $row
+   *
+   * @return integer
+   *  Either FILE_EXISTS_REPLACE (default) or FILE_EXISTS_RENAME, depending
+   *  on the current configuration.
+   */
+  protected function getOverwriteMode(Row $row) {
+    if (!empty($this->configuration['rename'])) {
+      $entity_id = $row->getDestinationProperty($this->getKey('id'));
+      if ($entity_id && ($entity = $this->storage->load($entity_id))) {
+        return FILE_EXISTS_RENAME;
+      }
+    }
+    return FILE_EXISTS_REPLACE;
+  }
+
+  /**
+   * Returns the directory component of a URI or path.
+   *
+   * For URIs like public://foo.txt, the full physical path of public://
+   * will be returned, since a scheme by itself will trip up certain file
+   * API functions (such as file_prepare_directory()).
+   *
+   * @param string $uri
+   *  The URI or path.
+   *
+   * @return false|string
+   */
+  protected function getDirectory($uri) {
+    $dir = $this->fileSystem->dirname($uri);
+    if (substr($dir, -3) == '://') {
+      return $this->fileSystem->realpath($dir);
+    }
+    else {
+      return $dir;
+    }
+  }
+
+  /**
+   * Returns if the source and destination URIs represent identical paths.
+   * If either URI is a remote stream, will return FALSE.
+   *
+   * @param string $source
+   *  The source URI.
+   * @param string $destination
+   *  The destination URI.
+   *
+   * @return boolean
+   */
+  protected function isLocationUnchanged($source, $destination) {
+    if ($this->isLocalUri($source) && $this->isLocalUri($destination)) {
+      return $this->fileSystem->realpath($source) === $this->fileSystem->realpath($destination);
     }
     else {
-      throw new MigrateException(t('File %source could not be copied to %destination.', array('%source' => $source, '%destination' => $destination)));
+      return FALSE;
     }
   }
 
   /**
+   * Returns if the given URI or path is considered local.
+   *
+   * A URI or path is considered local if it either has no scheme component,
+   * or the scheme is implemented by a stream wrapper which extends
+   * \Drupal\Core\StreamWrapper\LocalStream.
+   *
+   * @param string $uri
+   *  The URI or path to test.
+   *
+   * @return boolean
+   */
+  protected function isLocalUri($uri) {
+    $scheme = $this->fileSystem->uriScheme($uri);
+    return $scheme === FALSE || $this->streamWrapperManager->getViaScheme($scheme) instanceof LocalStream;
+  }
+
+  /**
    * Urlencode all the components of a remote filename.
    *
    * @param string $filename
@@ -114,18 +240,4 @@ protected function urlencode($filename) {
     return $filename;
   }
 
-  /**
-   * Check if a file is a temp file.
-   *
-   * @param string $file
-   *   The destination file path.
-   *
-   * @return bool
-   *   TRUE if the file is temporary otherwise FALSE.
-   */
-  protected function isTempFile($file) {
-    $tmp = 'temporary://';
-    return substr($file, 0, strlen($tmp)) === $tmp;
-  }
-
 }
diff --git a/core/modules/migrate/tests/src/Unit/destination/EntityFileTest.php b/core/modules/migrate/tests/src/Unit/destination/EntityFileTest.php
index 731c722..f962ed1 100644
--- a/core/modules/migrate/tests/src/Unit/destination/EntityFileTest.php
+++ b/core/modules/migrate/tests/src/Unit/destination/EntityFileTest.php
@@ -39,6 +39,9 @@ class EntityFileTest extends KernelTestBase {
   public function setUp() {
     parent::setUp();
     $this->destination = new TestEntityFile([]);
+    $this->destination->stringTranslation = \Drupal::getContainer()->get('string_translation');
+    $this->destination->streamWrapperManager = \Drupal::getContainer()->get('stream_wrapper_manager');
+    $this->destination->fileSystem = \Drupal::getContainer()->get('file_system');
 
     $this->installConfig(['system']);
     file_put_contents('/tmp/test-file.jpg', '');
@@ -70,6 +73,8 @@ protected function localFileDataProvider() {
       [['filepath' => 'core/modules/simpletest/files/image-test.jpg'], 'public://file1.jpg', TRUE, DRUPAL_ROOT . '/'],
       // Test a temporary file using an absolute path.
       [['filepath' => '/tmp/test-file.jpg'], 'temporary://test.jpg', TRUE, ''],
+      // Test a temporary file using a relative path.
+      [['filepath' => 'test-file.jpg'], 'temporary://core/modules/simpletest/files/test.jpg', TRUE, '/tmp/'],
       // Test a remote path to local.
       [['filepath' => 'core/modules/simpletest/files/image-test.jpg'], 'public://remote-file.jpg', TRUE, $base_url . '/'],
       // Test a remote path to local inside a folder that doesn't exist.
@@ -77,17 +82,20 @@ protected function localFileDataProvider() {
     ];
   }
 
-
   /**
    * Test that non-existent files throw an exception.
    */
   public function testNonExistentSourceFile() {
+    $destination = '/non/existent/file';
     try {
-      $this->doImport(['filepath' => '/none/existent/file'], 'public://wontmatter.jpg');
+      // If this test passes, doImport() will raise a MigrateException and
+      // we'll never reach fail().
+      $this->doImport(['filepath' => $destination], 'public://wontmatter.jpg');
+      $this->fail('Expected Drupal\migrate\MigrateException when importing ' . $destination);
+    }
+    catch (MigrateException $e) {
+      $this->assertIdentical($e->getMessage(), 'File <em class="placeholder">' . $destination . '</em> does not exist.');
     }
-    catch (MigrateException $e) {}
-    $destination = '/none/existent/file';
-    $this->assertIdentical($e->getMessage(), 'File <em class="placeholder">' . $destination . '</em> could not be copied to <em class="placeholder">public://wontmatter.jpg</em>.');
   }
 
   /**
@@ -132,6 +140,21 @@ class TestEntityFile extends EntityFile {
    */
   public $configuration;
 
+  /**
+   * @var \Drupal\Core\StringTranslation\TranslationInterface
+   */
+  public $stringTranslation;
+
+  /**
+   * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
+   */
+  public $streamWrapperManager;
+
+  /**
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  public $fileSystem;
+
   public function __construct($configuration) {
     $configuration +=  array(
       'source_base_path' => '',
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/FileUri.php b/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/FileUri.php
index 722cc96..b768809 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/FileUri.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/process/d6/FileUri.php
@@ -24,7 +24,6 @@ class FileUri extends ProcessPluginBase {
    * {@inheritdoc}
    */
   public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
-
     list($filepath, $file_directory_path, $temp_directory_path, $is_public) = $value;
 
     // Specific handling using $temp_directory_path for temporary files.
