diff --git a/src/Symfony/Component/Mime/Part/DataPart.php b/src/Symfony/Component/Mime/Part/DataPart.php index e80a83946ef2e..4247ce798d868 100644 --- a/src/Symfony/Component/Mime/Part/DataPart.php +++ b/src/Symfony/Component/Mime/Part/DataPart.php @@ -61,13 +61,20 @@ public static function fromPath(string $path, string $name = null, string $conte $contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; } - if (!is_file($path) || !is_readable($path)) { + if ((is_file($path) && !is_readable($path)) || is_dir($path)) { throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path)); } if (false === $handle = @fopen($path, 'r', false)) { throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path)); } + + if (!is_file($path)) { + $cache = fopen('php://temp', 'r+'); + stream_copy_to_stream($handle, $cache); + $handle = $cache; + } + $p = new self($handle, $name ?: basename($path), $contentType); $p->handle = $handle; diff --git a/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php b/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php index 4d5b692744327..34a379c2a983f 100644 --- a/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php +++ b/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php @@ -134,6 +134,30 @@ public function testFromPathWithNotAFile() DataPart::fromPath(__DIR__.'/../Fixtures/mimetypes/'); } + /** + * @group network + */ + public function testFromPathWithUrl() + { + if (!\in_array('https', stream_get_wrappers())) { + $this->markTestSkipped('"https" stream wrapper is not enabled.'); + } + + $p = DataPart::fromPath($file = 'https://symfony.com/images/common/logo/logo_symfony_header.png'); + $content = file_get_contents($file); + $this->assertEquals($content, $p->getBody()); + $maxLineLength = 76; + $this->assertEquals(substr(base64_encode($content), 0, $maxLineLength), substr($p->bodyToString(), 0, $maxLineLength)); + $this->assertEquals(substr(base64_encode($content), 0, $maxLineLength), substr(implode('', iterator_to_array($p->bodyToIterable())), 0, $maxLineLength)); + $this->assertEquals('image', $p->getMediaType()); + $this->assertEquals('png', $p->getMediaSubType()); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'image/png', ['name' => 'logo_symfony_header.png']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'logo_symfony_header.png', 'filename' => 'logo_symfony_header.png']) + ), $p->getPreparedHeaders()); + } + public function testHasContentId() { $p = new DataPart('content');