Skip to content
Permalink
Browse files

Rough implementation of withFile() & withDownload())

  • Loading branch information...
markstory committed Dec 9, 2016
1 parent 116b8fe commit 549b65c6984fbbee54f5ab10f8eeb9d9f33b03e1
Showing with 329 additions and 21 deletions.
  1. +80 −0 src/Network/Response.php
  2. +249 −21 tests/TestCase/Network/ResponseTest.php
@@ -1770,12 +1770,24 @@ public function outputCompressed()
*
* @param string $filename The name of the file as the browser will download the response
* @return void
* @deprecated 3.4.0 Use withDownload() instead.
*/
public function download($filename)
{
$this->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
}
/**
* Create a new instance with the Content-Disposition header set.
*
* @param string $filename The name of the file as the browser will download the response
* @return static
*/
public function withDownload($filename)
{
return $this->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
}
/**
* Sets the protocol to be used when sending the response. Defaults to HTTP/1.1
* If called with no arguments, it will return the current configured protocol
@@ -2148,6 +2160,72 @@ public function file($path, array $options = [])
$this->_file = $file;
}
public function withFile($path, array $options = [])
{
// TODO move validation into a helper method.
if (strpos($path, '../') !== false || strpos($path, '..\\') !== false) {
throw new NotFoundException('The requested file contains `..` and will not be read.');
}
if (!is_file($path)) {
$path = APP . $path;
}
$file = new File($path);
if (!$file->exists() || !$file->readable()) {
if (Configure::read('debug')) {
throw new NotFoundException(sprintf('The requested file %s was not found or not readable', $path));
}
throw new NotFoundException(__d('cake', 'The requested file was not found'));
}
// end refactor.
$options += [
'name' => null,
'download' => null
];
$extension = strtolower($file->ext());
if ((!$extension || $this->type($extension) === false) && $options['download'] === null) {
$options['download'] = true;
}
$new = clone $this;
$fileSize = $file->size();
if ($options['download']) {
$agent = env('HTTP_USER_AGENT');
if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) {
$contentType = 'application/octet-stream';
} elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
$contentType = 'application/force-download';
}
if (!empty($contentType)) {
$new = $new->withType($contentType);
}
if ($options['name'] === null) {
$name = $file->name;
} else {
$name = $options['name'];
}
$new = $new->withDownload($name)
->withHeader('Content-Transfer-Encoding', 'binary');
}
$new = $new->withHeader('Accept-Ranges', 'bytes');
$httpRange = env('HTTP_RANGE');
if (isset($httpRange)) {
$new->_fileRange($file, $httpRange);
} else {
$new = $new->withHeader('Content-Length', (string)$fileSize);
}
$new->_file = $file;
$new->stream = new Stream($file->path, 'rb');
return $new;
}
/**
* Get the current file if one exists.
*
@@ -2167,6 +2245,8 @@ public function getFile()
* @param \Cake\Filesystem\File $file The file to set a range on.
* @param string $httpRange The range to use.
* @return void
* @deprecated 3.4.0 Long term this needs to be refactored to follow immutable paradigms.
* However for now, it is simpler to leave this alone.
*/
protected function _fileRange($file, $httpRange)
{
Oops, something went wrong.

0 comments on commit 549b65c

Please sign in to comment.
You can’t perform that action at this time.