-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[HttpFoundation] Added BinaryFileResponse #2606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\HttpFoundation; | ||
|
||
use Symfony\Component\HttpFoundation\File\File; | ||
use Symfony\Component\HttpFoundation\File\Exception\FileException; | ||
|
||
/** | ||
* BinaryFileResponse represents an HTTP response representing a binary file. | ||
* | ||
* @author Jordan Alliot <jordan.alliot@gmail.com> | ||
*/ | ||
class BinaryFileResponse extends Response | ||
{ | ||
private $file; | ||
|
||
/** | ||
* Creates a BinaryFileResponse. | ||
* | ||
* @param SplFileInfo|string $file The file to download | ||
* @param integer $status The response status code | ||
* @param array $headers An array of response headers | ||
* @param boolean $autoValidation Whether ETag and Last-Modified headers | ||
* are automatically set or not | ||
* @param boolean $public Files are public by default | ||
*/ | ||
public function __construct($file, $status = 200, $headers = array(), $autoValidation = true, $public = true) | ||
{ | ||
parent::__construct('', $status, $headers); | ||
|
||
$this->setFile($file); | ||
|
||
$this->headers->set('Content-Transfer-Encoding', 'binary'); | ||
|
||
if (true === $autoValidation) { | ||
$this->setAutoLastModified(); | ||
$this->setAutoEtag(); | ||
} | ||
|
||
if (true === $public) { | ||
$this->setPublic(); | ||
} | ||
} | ||
|
||
/** | ||
* Sets the file to download. | ||
* | ||
* Also sets some headers for the download, namely | ||
* Content-Disposition, Content-Length and Content-Type. | ||
* | ||
* @param SplFileInfo|string $file The file to download | ||
*/ | ||
public function setFile($file) | ||
{ | ||
if (null === $file) { | ||
throw new \InvalidArgumentException('File cannot be null.'); | ||
} | ||
|
||
$file = new File((string) $file, true); | ||
|
||
if (!$file->isReadable()) { | ||
throw new FileException('File must be readable.'); | ||
} | ||
|
||
$this->file = $file; | ||
|
||
$this->makeDisposition(); | ||
$this->headers->set('Content-Length', $file->getSize()); | ||
$this->headers->set('Content-Type', $file->getMimeType() ?: 'application/octet-stream'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a good idea to make it possible to force a download? An simple setter like setForceDownload() which always sets the 'application/octet-stream'. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to force the download, the proper way is not to force the mime type but to change the content disposition to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, your correct. I have not used this in a while. Still, having an function name like this much clearer then makeDisposition. |
||
} | ||
|
||
/** | ||
* Returns the file. | ||
* | ||
* @return File | ||
*/ | ||
public function getFile() | ||
{ | ||
return $this->file; | ||
} | ||
|
||
/** | ||
* Sets the Content-Disposition header. | ||
* | ||
* @param string $disposition Either "inline" or "attachment" (default) | ||
* @param string $filename Name of the file (by default the original file name) | ||
* May be unicode | ||
* @param string $filenameFallback A string containing only ASCII characters that | ||
* is semantically equivalent to $filename. If the filename is already ASCII, | ||
* it can be omitted, or just copied from $filename | ||
*/ | ||
public function makeDisposition($disposition = null, $filename = '', $filenameFallback = '') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is wrong as the method behavior is totally different from the parent. Why not set the content disposition without overriding this method? |
||
{ | ||
$this->headers->set('Content-Disposition', $this->headers->makeDisposition( | ||
$disposition ?: ResponseHeaderBag::DISPOSITION_ATTACHMENT, | ||
$filename ?: $this->file->getBasename(), | ||
$filenameFallback ?: rawurlencode($this->file->getBasename()) | ||
)); | ||
} | ||
|
||
/** | ||
* Automatically sets the Last-Modified header according to the file modification date. | ||
*/ | ||
public function setAutoLastModified() | ||
{ | ||
$this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); | ||
} | ||
|
||
/** | ||
* Automatically sets the ETag header according to the checksum of the file. | ||
*/ | ||
public function setAutoEtag() | ||
{ | ||
$this->setEtag(sha1_file($this->file->getPathname())); | ||
} | ||
|
||
/** | ||
* Sends the file. | ||
*/ | ||
public function sendContent() | ||
{ | ||
if (!$this->isSuccessful()) { | ||
parent::sendContent(); | ||
return; | ||
} | ||
|
||
readfile($this->file->getPathname()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should simply be
if ($public) {