diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 605d979..2af47c3 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -11,8 +11,10 @@
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\Core\Site\Settings;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -87,18 +89,22 @@ public function onRespond(FilterResponseEvent $event) {
     if ($is_cacheable && $this->config->get('cache.page.max_age') > 0) {
       if (!$this->isCacheControlCustomized($response)) {
         $this->setResponseCacheable($response, $request);
+
+        // Currently it is not possible to cache some types of responses. Therefore
+        // exclude binary file responses (generated files, e.g. images with image
+        // styles) and streamed responses (files directly read from the disk).
+        // see: https://github.com/symfony/symfony/issues/9128#issuecomment-25088678
+        if ($this->config->get('cache.page.use_internal') && !($response instanceof BinaryFileResponse) && !($response instanceof StreamedResponse)) {
+          // Store the response in the internal page cache.
+          drupal_page_set_cache($response, $request);
+          $response->headers->set('X-Drupal-Cache', 'MISS');
+          drupal_serve_page_from_cache($response, $request);
+        }
       }
     }
     else {
       $this->setResponseNotCacheable($response, $request);
     }
-
-    // Store the response in the internal page cache.
-    if ($is_cacheable && $this->config->get('cache.page.use_internal')) {
-      drupal_page_set_cache($response, $request);
-      $response->headers->set('X-Drupal-Cache', 'MISS');
-      drupal_serve_page_from_cache($response, $request);
-    }
   }
 
   /**
diff --git a/core/modules/file/src/Tests/DownloadTest.php b/core/modules/file/src/Tests/DownloadTest.php
index e39b39c..51ae9ce 100644
--- a/core/modules/file/src/Tests/DownloadTest.php
+++ b/core/modules/file/src/Tests/DownloadTest.php
@@ -53,7 +53,27 @@ function testPublicFileTransfer() {
   /**
    * Test the private file transfer system.
    */
-  function testPrivateFileTransfer() {
+  public function testPrivateFileTransferWithoutPageCache() {
+    $this->doPrivateFileTransferTest();
+  }
+
+  /**
+   * Test the private file transfer system with page cache.
+   */
+  public function testPrivateFileTransferWithPageCache() {
+    // Turn on page caching and rerun the test.
+    $config = \Drupal::config('system.performance');
+    $config->set('cache.page.use_internal', 1);
+    $config->set('cache.page.max_age', 300);
+    $config->save();
+
+    $this->doPrivateFileTransferTest();
+  }
+
+  /**
+   * Test the private file transfer system.
+   */
+  protected function doPrivateFileTransferTest() {
     // Set file downloads to private so handler functions get called.
 
     // Create a file.
@@ -64,8 +84,8 @@ function testPrivateFileTransfer() {
     // Set file_test access header to allow the download.
     file_test_set_return('download', array('x-foo' => 'Bar'));
     $this->drupalGet($url);
-    $headers = $this->drupalGetHeaders();
-    $this->assertEqual($headers['x-foo'], 'Bar', 'Found header set by file_test module on private download.');
+    $this->assertEqual($this->drupalGetHeader('x-foo'), 'Bar', 'Found header set by file_test module on private download.');
+    $this->assertFalse($this->drupalGetHeader('x-drupal-cache'), 'Page cache is disabled on private file download.');
     $this->assertResponse(200, 'Correctly allowed access to a file when file_test provides headers.');
 
     // Test that the file transferred correctly.
diff --git a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
index 5b0c2d6..4b16530 100644
--- a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
+++ b/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
@@ -85,6 +85,22 @@ function testImageStyleUrlAndPathPrivateUnclean() {
   }
 
   /**
+   * Tests an image style URL using the "public://" scheme and page cache.
+   */
+  public function testImageStyleUrlAndPathPublicWithPageCache() {
+    $this->enablePageCache();
+    $this->doImageStyleUrlAndPathTests('public');
+  }
+
+  /**
+   * Tests an image style URL using the "private://" scheme and page cache.
+   */
+  public function testImageStyleUrlAndPathPrivateWithPageCache() {
+    $this->enablePageCache();
+    $this->doImageStyleUrlAndPathTests('private');
+  }
+
+  /**
    * Tests an image style URL with a file URL that has an extra slash in it.
    */
   function testImageStyleUrlExtraSlash() {
@@ -232,4 +248,15 @@ function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash =
     $this->assertResponse(200, 'Image was accessible at the URL with a missing token.');
   }
 
+  /**
+   * Turn on page caching.
+   */
+  protected function enablePageCache() {
+    // Turn on page caching and rerun the test.
+    $config = \Drupal::config('system.performance');
+    $config->set('cache.page.use_internal', 1);
+    $config->set('cache.page.max_age', 300);
+    $config->save();
+  }
+
 }
