diff --git a/core/includes/common.inc b/core/includes/common.inc
index 23f6ce3..cdcc70e 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -21,8 +21,10 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
 use Drupal\Core\PhpStorage\PhpStorageFactory;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Datetime\DrupalDateTime;
@@ -2684,8 +2686,20 @@ function _drupal_bootstrap_full($skip = FALSE) {
  *   The request for this page.
  *
  * @see drupal_page_header()
+ *
+ * @return bool
+ *   Returns TRUE if the response has been recorded in the cache, FALSE
+ *   otherwise.
  */
 function drupal_page_set_cache(Response $response, Request $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 (($response instanceof BinaryFileResponse) || ($response instanceof StreamedResponse)) {
+    return FALSE;
+  }
+
   // Check if the current page may be compressed.
   if (\Drupal::config('system.performance')->get('response.gzip') &&
     !$response->headers->get('Content-Encoding') && extension_loaded('zlib')) {
@@ -2709,6 +2723,8 @@ function drupal_page_set_cache(Response $response, Request $request) {
   $cid = drupal_page_cache_get_cid($request);
   $tags = HtmlViewSubscriber::convertHeaderToCacheTags($response->headers->get('X-Drupal-Cache-Tags'));
   \Drupal::cache('render')->set($cid, $response, $expire, $tags);
+
+  return TRUE;
 }
 
 /**
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 605d979..7679a20 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -94,8 +94,7 @@ public function onRespond(FilterResponseEvent $event) {
     }
 
     // Store the response in the internal page cache.
-    if ($is_cacheable && $this->config->get('cache.page.use_internal')) {
-      drupal_page_set_cache($response, $request);
+    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/Controller/ImageStyleDownloadController.php b/core/modules/image/src/Controller/ImageStyleDownloadController.php
index 191a6c7..bf4f9d9 100644
--- a/core/modules/image/src/Controller/ImageStyleDownloadController.php
+++ b/core/modules/image/src/Controller/ImageStyleDownloadController.php
@@ -143,6 +143,7 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st
     }
 
     if ($success) {
+      drupal_page_is_cacheable(FALSE);
       $image = $this->imageFactory->get($derivative_uri);
       $uri = $image->getSource();
       $headers += array(
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();
+  }
+
 }
