diff --git a/core/modules/migrate_drupal/config/optional/migrate.migration.d7_file.yml b/core/modules/migrate_drupal/config/optional/migrate.migration.d7_file.yml
new file mode 100644
index 0000000..677ab43
--- /dev/null
+++ b/core/modules/migrate_drupal/config/optional/migrate.migration.d7_file.yml
@@ -0,0 +1,27 @@
+# Every migration that saves into {file_managed} must have the d7_file
+# migration as an optional dependency to ensure d7_file runs first.
+id: d7_file
+label: Drupal 7 files
+migration_tags:
+  - Drupal 7
+source:
+  plugin: d7_file
+process:
+  fid: fid
+  filename: filename
+  uri: uri
+  filemime: filemime
+  # filesize is dynamically computed when files are saved, so there is no point
+  # in migrating this value.
+  # filesize: filesize
+  status: status
+  created: timestamp
+  changed: timestamp
+  uid: uid
+destination:
+  plugin: entity:file
+  source_path_property: uri
+dependencies:
+  module:
+    - file
+    - migrate_drupal
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/File.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/File.php
index ff51c62..bc7a877 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/File.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/File.php
@@ -58,7 +58,6 @@ public function query() {
     return $query;
   }
 
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/File.php b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/File.php
new file mode 100644
index 0000000..43e11e9
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/File.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\source\d7\File.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d7;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 7 file source from database.
+ *
+ * @MigrateSource(
+ *   id = "d7_file"
+ * )
+ */
+class File extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('file_managed', 'f')
+      ->fields('f')
+      ->orderBy('timestamp');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'fid' => $this->t('File ID'),
+      'uid' => $this->t('The {users}.uid who added the file. If set to 0, this file was added by an anonymous user.'),
+      'filename' => $this->t('File name'),
+      'filepath' => $this->t('File path'),
+      'filemime' => $this->t('File Mime Type'),
+      'status' => $this->t('The published status of a file.'),
+      'timestamp' => $this->t('The time that the file was added.'),
+    );
+  }
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['fid']['type'] = 'integer';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/src/Tests/d7/MigrateFileTest.php b/core/modules/migrate_drupal/src/Tests/d7/MigrateFileTest.php
new file mode 100644
index 0000000..e5c3a6d
--- /dev/null
+++ b/core/modules/migrate_drupal/src/Tests/d7/MigrateFileTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d7\MigrateFileTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d7;
+
+use Drupal\file\Entity\File;
+use Drupal\file\FileInterface;
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Migrates all files in the file_managed table.
+ *
+ * @group migrate_drupal 7.x
+ * @dumpFile d7/FileManaged.php
+ * @migration d7_file
+ */
+class MigrateFileTest extends MigrateDrupal7TestBase {
+
+  static $modules = array('file');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->loadDumps([
+      $this->getDumpDirectory() . '/FileManaged.php',
+    ]);
+    $this->installEntitySchema('file');
+
+    touch('public://cube.jpeg');
+    file_put_contents('public://cube.jpeg', str_repeat('*', 3620));
+
+    $migration = entity_load('migration', 'd7_file');
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) {
+    /** @var \Drupal\file\FileInterface $file */
+    $file = File::load($id);
+    $this->assertTrue($file instanceof FileInterface);
+    $this->assertIdentical($name, $file->getFilename());
+    $this->assertIdentical($uri, $file->getFileUri());
+    $this->assertIdentical($mime, $file->getMimeType());
+    $this->assertIdentical($size, $file->getSize());
+    // @TODO Check status, since that's important for files.
+    $this->assertIdentical($created, $file->getCreatedTime());
+    $this->assertIdentical($changed, $file->getChangedTime());
+    $this->assertIdentical($uid, $file->getOwnerId());
+  }
+
+  /**
+   * Tests that all expected files are migrated.
+   */
+  public function testFileMigration() {
+    $this->assertEntity(1, 'cube.jpeg', 'public://cube.jpeg', 'image/jpeg', '3620', '1421727515', '1421727515', '1');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/src/Unit/source/d7/FileTest.php b/core/modules/migrate_drupal/tests/src/Unit/source/d7/FileTest.php
new file mode 100644
index 0000000..b473921
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/src/Unit/source/d7/FileTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\migrate_drupal\Unit\source\d7\FileTest.
+ */
+
+namespace Drupal\Tests\migrate_drupal\Unit\source\d7;
+
+use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
+
+/**
+ * Tests D7 file source plugin.
+ *
+ * @group migrate_drupal
+ */
+class FileTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d7\File';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    'source' => array(
+      'plugin' => 'd7_file',
+    ),
+  );
+
+  protected $expectedResults = [
+    [
+      'fid' => '1',
+      'uid' => '1',
+      'filename' => 'cube.jpeg',
+      'uri' => 'public://cube.jpeg',
+      'filemime' => 'image/jpeg',
+      'filesize' => '3620',
+      'status' => '1',
+      'timestamp' => '1421727515',
+    ],
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->databaseContents['file_managed'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+}
+
+namespace Drupal\Tests\migrate_drupal\Unit\source\d7;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d7\File;
+
+class TestFile extends File {
+  public function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
