mirror of
https://github.com/Ne-Lexa/php-zip.git
synced 2025-07-18 06:31:13 +02:00
issue #8 - Support inline Content-Disposition and empty output filename.
This commit is contained in:
17
phpunit.xml
17
phpunit.xml
@@ -1,10 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<phpunit bootstrap="./vendor/autoload.php" colors="true">
|
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
colors="true"
|
||||||
|
bootstrap="vendor/autoload.php">
|
||||||
|
<php>
|
||||||
|
<ini name="error_reporting" value="-1"/>
|
||||||
|
</php>
|
||||||
|
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="PhpZip test suite">
|
<testsuite name="PhpZip test suite">
|
||||||
<directory>./tests</directory>
|
<directory>tests</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory>src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
</phpunit>
|
</phpunit>
|
@@ -1226,61 +1226,64 @@ class ZipFile implements ZipFileInterface
|
|||||||
* Output .ZIP archive as attachment.
|
* Output .ZIP archive as attachment.
|
||||||
* Die after output.
|
* Die after output.
|
||||||
*
|
*
|
||||||
* @param string $outputFilename
|
* @param string $outputFilename Output filename
|
||||||
* @param string|null $mimeType
|
* @param string|null $mimeType Mime-Type
|
||||||
|
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function outputAsAttachment($outputFilename, $mimeType = null)
|
public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true)
|
||||||
{
|
{
|
||||||
$outputFilename = (string)$outputFilename;
|
$outputFilename = (string)$outputFilename;
|
||||||
if (strlen($outputFilename) === 0) {
|
|
||||||
throw new InvalidArgumentException("Output filename is empty.");
|
if (empty($mimeType) || !is_string($mimeType) && !empty($outputFilename)) {
|
||||||
}
|
|
||||||
if (empty($mimeType) || !is_string($mimeType)) {
|
|
||||||
$ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
|
$ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
|
if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
|
||||||
$mimeType = self::$defaultMimeTypes[$ext];
|
$mimeType = self::$defaultMimeTypes[$ext];
|
||||||
} else {
|
|
||||||
$mimeType = self::$defaultMimeTypes['zip'];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$outputFilename = basename($outputFilename);
|
if (empty($mimeType)) {
|
||||||
|
$mimeType = self::$defaultMimeTypes['zip'];
|
||||||
|
}
|
||||||
|
|
||||||
$content = $this->outputAsString();
|
$content = $this->outputAsString();
|
||||||
$this->close();
|
$this->close();
|
||||||
|
|
||||||
|
$headerContentDisposition = 'Content-Disposition: ' . ($attachment ? 'attachment' : 'inline');
|
||||||
|
if (!empty($outputFilename)) {
|
||||||
|
$headerContentDisposition .= '; filename="' . basename($outputFilename) . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
header($headerContentDisposition);
|
||||||
header("Content-Type: " . $mimeType);
|
header("Content-Type: " . $mimeType);
|
||||||
header('Content-Disposition: attachment; filename="' . $outputFilename . '"');
|
|
||||||
header("Content-Length: " . strlen($content));
|
header("Content-Length: " . strlen($content));
|
||||||
exit($content);
|
exit($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output .ZIP archive as PSR-Message Response.
|
* Output .ZIP archive as PSR-7 Response.
|
||||||
*
|
*
|
||||||
* @param ResponseInterface $response
|
* @param ResponseInterface $response Instance PSR-7 Response
|
||||||
* @param string $outputFilename
|
* @param string $outputFilename Output filename
|
||||||
* @param string|null $mimeType
|
* @param string|null $mimeType Mime-Type
|
||||||
|
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||||
* @return ResponseInterface
|
* @return ResponseInterface
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null)
|
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true)
|
||||||
{
|
{
|
||||||
$outputFilename = (string)$outputFilename;
|
$outputFilename = (string)$outputFilename;
|
||||||
if (strlen($outputFilename) === 0) {
|
|
||||||
throw new InvalidArgumentException("Output filename is empty.");
|
if (empty($mimeType) || !is_string($mimeType) && !empty($outputFilename)) {
|
||||||
}
|
|
||||||
if (empty($mimeType) || !is_string($mimeType)) {
|
|
||||||
$ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
|
$ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
|
if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
|
||||||
$mimeType = self::$defaultMimeTypes[$ext];
|
$mimeType = self::$defaultMimeTypes[$ext];
|
||||||
} else {
|
|
||||||
$mimeType = self::$defaultMimeTypes['zip'];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$outputFilename = basename($outputFilename);
|
if (empty($mimeType)) {
|
||||||
|
$mimeType = self::$defaultMimeTypes['zip'];
|
||||||
|
}
|
||||||
|
|
||||||
if (!($handle = fopen('php://memory', 'w+b'))) {
|
if (!($handle = fopen('php://memory', 'w+b'))) {
|
||||||
throw new InvalidArgumentException("Memory can not open from write.");
|
throw new InvalidArgumentException("Memory can not open from write.");
|
||||||
@@ -1288,9 +1291,14 @@ class ZipFile implements ZipFileInterface
|
|||||||
$this->writeZipToStream($handle);
|
$this->writeZipToStream($handle);
|
||||||
rewind($handle);
|
rewind($handle);
|
||||||
|
|
||||||
|
$contentDispositionValue = ($attachment ? 'attachment' : 'inline');
|
||||||
|
if (!empty($outputFilename)) {
|
||||||
|
$contentDispositionValue .= '; filename="' . basename($outputFilename) . '"';
|
||||||
|
}
|
||||||
|
|
||||||
$stream = new ResponseStream($handle);
|
$stream = new ResponseStream($handle);
|
||||||
$response->withHeader('Content-Type', $mimeType);
|
$response->withHeader('Content-Type', $mimeType);
|
||||||
$response->withHeader('Content-Disposition', 'attachment; filename="' . $outputFilename . '"');
|
$response->withHeader('Content-Disposition', $contentDispositionValue);
|
||||||
$response->withHeader('Content-Length', $stream->getSize());
|
$response->withHeader('Content-Length', $stream->getSize());
|
||||||
$response->withBody($stream);
|
$response->withBody($stream);
|
||||||
return $response;
|
return $response;
|
||||||
@@ -1348,11 +1356,15 @@ class ZipFile implements ZipFileInterface
|
|||||||
$content = $this->outputAsString();
|
$content = $this->outputAsString();
|
||||||
$this->close();
|
$this->close();
|
||||||
if ('plainfile' === $meta['wrapper_type']) {
|
if ('plainfile' === $meta['wrapper_type']) {
|
||||||
if (file_put_contents($meta['uri'], $content) === false) {
|
/**
|
||||||
throw new ZipException("Can not overwrite the zip file in the {$meta['uri']} file.");
|
* @var resource $uri
|
||||||
|
*/
|
||||||
|
$uri = $meta['uri'];
|
||||||
|
if (file_put_contents($uri, $content) === false) {
|
||||||
|
throw new ZipException("Can not overwrite the zip file in the {$uri} file.");
|
||||||
}
|
}
|
||||||
if (!($handle = @fopen($meta['uri'], 'rb'))) {
|
if (!($handle = @fopen($uri, 'rb'))) {
|
||||||
throw new ZipException("File {$meta['uri']} can't open.");
|
throw new ZipException("File {$uri} can't open.");
|
||||||
}
|
}
|
||||||
return $this->openFromStream($handle);
|
return $this->openFromStream($handle);
|
||||||
}
|
}
|
||||||
|
@@ -592,22 +592,23 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
|
|||||||
* Output .ZIP archive as attachment.
|
* Output .ZIP archive as attachment.
|
||||||
* Die after output.
|
* Die after output.
|
||||||
*
|
*
|
||||||
* @param string $outputFilename
|
* @param string $outputFilename Output filename
|
||||||
* @param string|null $mimeType
|
* @param string|null $mimeType Mime-Type
|
||||||
* @throws InvalidArgumentException
|
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||||
*/
|
*/
|
||||||
public function outputAsAttachment($outputFilename, $mimeType = null);
|
public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output .ZIP archive as PSR-Message Response.
|
* Output .ZIP archive as PSR-7 Response.
|
||||||
*
|
*
|
||||||
* @param ResponseInterface $response
|
* @param ResponseInterface $response Instance PSR-7 Response
|
||||||
* @param string $outputFilename
|
* @param string $outputFilename Output filename
|
||||||
* @param string|null $mimeType
|
* @param string|null $mimeType Mime-Type
|
||||||
|
* @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
|
||||||
* @return ResponseInterface
|
* @return ResponseInterface
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null);
|
public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the zip archive as a string.
|
* Returns the zip archive as a string.
|
||||||
|
@@ -30,7 +30,7 @@ class ZipFileTest extends ZipTestCase
|
|||||||
*/
|
*/
|
||||||
public function testOpenFileCantOpen()
|
public function testOpenFileCantOpen()
|
||||||
{
|
{
|
||||||
if (0 === posix_getuid()){
|
if (0 === posix_getuid()) {
|
||||||
$this->markTestSkipped('Skip the test for a user with root privileges');
|
$this->markTestSkipped('Skip the test for a user with root privileges');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,7 +1007,7 @@ class ZipFileTest extends ZipTestCase
|
|||||||
*/
|
*/
|
||||||
public function testExtractFail3()
|
public function testExtractFail3()
|
||||||
{
|
{
|
||||||
if (0 === posix_getuid()){
|
if (0 === posix_getuid()) {
|
||||||
$this->markTestSkipped('Skip the test for a user with root privileges');
|
$this->markTestSkipped('Skip the test for a user with root privileges');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,7 +1213,7 @@ class ZipFileTest extends ZipTestCase
|
|||||||
*/
|
*/
|
||||||
public function testAddFileCantOpen()
|
public function testAddFileCantOpen()
|
||||||
{
|
{
|
||||||
if (0 === posix_getuid()){
|
if (0 === posix_getuid()) {
|
||||||
$this->markTestSkipped('Skip the test for a user with root privileges');
|
$this->markTestSkipped('Skip the test for a user with root privileges');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1501,7 +1501,7 @@ class ZipFileTest extends ZipTestCase
|
|||||||
*/
|
*/
|
||||||
public function testSaveAsFileNotWritable()
|
public function testSaveAsFileNotWritable()
|
||||||
{
|
{
|
||||||
if (0 === posix_getuid()){
|
if (0 === posix_getuid()) {
|
||||||
$this->markTestSkipped('Skip the test for a user with root privileges');
|
$this->markTestSkipped('Skip the test for a user with root privileges');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1662,26 +1662,6 @@ class ZipFileTest extends ZipTestCase
|
|||||||
$zipFile->addEmptyDir("");
|
$zipFile->addEmptyDir("");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \PhpZip\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Output filename is empty.
|
|
||||||
*/
|
|
||||||
public function testOutputAsAttachmentNullName()
|
|
||||||
{
|
|
||||||
$zipFile = new ZipFile();
|
|
||||||
$zipFile->outputAsAttachment(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \PhpZip\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Output filename is empty.
|
|
||||||
*/
|
|
||||||
public function testOutputAsAttachmentEmptyName()
|
|
||||||
{
|
|
||||||
$zipFile = new ZipFile();
|
|
||||||
$zipFile->outputAsAttachment('');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \PhpZip\Exception\ZipNotFoundEntry
|
* @expectedException \PhpZip\Exception\ZipNotFoundEntry
|
||||||
* @expectedExceptionMessage Zip entry bad entry name not found
|
* @expectedExceptionMessage Zip entry bad entry name not found
|
||||||
@@ -1916,18 +1896,6 @@ class ZipFileTest extends ZipTestCase
|
|||||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \PhpZip\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Output filename is empty.
|
|
||||||
*/
|
|
||||||
public function testInvalidPsrResponse()
|
|
||||||
{
|
|
||||||
$zipFile = new ZipFile();
|
|
||||||
$zipFile['file'] = 'content';
|
|
||||||
$response = $this->getMock(ResponseInterface::class);
|
|
||||||
$zipFile->outputAsResponse($response, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCompressionLevel()
|
public function testCompressionLevel()
|
||||||
{
|
{
|
||||||
$zipFile = new ZipFile();
|
$zipFile = new ZipFile();
|
||||||
|
Reference in New Issue
Block a user