diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index e2812f8e2252b..3e3bd6fd3addc 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -663,8 +663,8 @@ public function tempnam($dir, $prefix) /** * Atomically dumps content into a file. * - * @param string $filename The file to be written to - * @param string $content The data to write into the file + * @param string $filename The file to be written to + * @param string|resource $content The data to write into the file * * @throws IOException if the file cannot be written to */ @@ -684,8 +684,20 @@ public function dumpFile($filename, $content) // when the filesystem supports chmod. $tmpFile = $this->tempnam($dir, basename($filename)); - if (false === @file_put_contents($tmpFile, $content)) { - throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); + $expectedSize = false; + + if (\is_resource($content)) { + $stat = fstat($content); + if (false !== $stat) { + $expectedSize = $stat['size'] - ftell($content); + } + } else { + $expectedSize = array_sum(array_map('strlen', (array) $content)); + } + + $actualSize = @file_put_contents($tmpFile, $content); + if ((false === $expectedSize && false === $actualSize) && ($actualSize !== $expectedSize)) { + throw new IOException(sprintf('Failed to write file "%s". Wrote %d of %d bytes.', $filename, $actualSize, $expectedSize), 0, null, $filename); } @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 8ac80437fe5dc..8666de00b99a6 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1505,6 +1505,38 @@ public function testDumpFileWithResource() $this->assertStringEqualsFile($filename, 'bar'); } + public function testDumpPartialFileWithResource() + { + $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt'; + + $resource = fopen('php://memory', 'rw'); + fwrite($resource, 'bar'); + fseek($resource, 1); + + $this->filesystem->dumpFile($filename, $resource); + + fclose($resource); + $this->assertFileExists($filename); + $this->assertStringEqualsFile($filename, 'ar'); + } + + /** + * @group network + */ + public function testDumpFileWithHttpStream() + { + if (!\in_array('https', stream_get_wrappers())) { + $this->markTestSkipped('"https" stream wrapper is not enabled.'); + } + $sourceFilePath = 'https://symfony.com/images/common/logo/logo_symfony_header.png'; + $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'dump_target_file'; + + $this->filesystem->dumpFile($targetFilePath, fopen($sourceFilePath, 'rb')); + + $this->assertFileExists($targetFilePath); + $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath)); + } + public function testDumpFileOverwritesAnExistingFile() { $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt';
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: