Optimized code.

This commit is contained in:
李铭昕 2019-08-29 10:55:56 +08:00
parent 09baa12d22
commit cab20303cf
5 changed files with 61 additions and 39 deletions

View File

@ -7,6 +7,7 @@
- [#418](https://github.com/hyperf-cloud/hyperf/pull/418) Allows send WebSocket message to any fd in current server, even the worker process does not hold the fd - [#418](https://github.com/hyperf-cloud/hyperf/pull/418) Allows send WebSocket message to any fd in current server, even the worker process does not hold the fd
- [#420](https://github.com/hyperf-cloud/hyperf/pull/420) Added listener for model. - [#420](https://github.com/hyperf-cloud/hyperf/pull/420) Added listener for model.
- [#441](https://github.com/hyperf-cloud/hyperf/pull/441) Automatically close the spare redis client when it is used in low frequency. - [#441](https://github.com/hyperf-cloud/hyperf/pull/441) Automatically close the spare redis client when it is used in low frequency.
- [#455](https://github.com/hyperf-cloud/hyperf/pull/455) Added download method for Response.
## Changed ## Changed

View File

@ -13,8 +13,8 @@ declare(strict_types=1);
namespace Hyperf\HttpMessage\Server; namespace Hyperf\HttpMessage\Server;
use Hyperf\HttpMessage\Cookie\Cookie; use Hyperf\HttpMessage\Cookie\Cookie;
use Hyperf\HttpMessage\Stream\FileInterface;
use Hyperf\HttpMessage\Stream\SwooleStream; use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpMessage\Stream\SwooleFileStream;
class Response extends \Hyperf\HttpMessage\Base\Response class Response extends \Hyperf\HttpMessage\Base\Response
{ {
@ -47,8 +47,8 @@ class Response extends \Hyperf\HttpMessage\Base\Response
$this->buildSwooleResponse($this->swooleResponse, $this); $this->buildSwooleResponse($this->swooleResponse, $this);
$content = $this->getBody(); $content = $this->getBody();
if($content instanceof SwooleFileStream){ if ($content instanceof FileInterface) {
return $this->swooleResponse->sendfile($content->getContents()); return $this->swooleResponse->sendfile($content->getFilename());
} }
$this->swooleResponse->end($content->getContents()); $this->swooleResponse->end($content->getContents());
} }
@ -101,7 +101,7 @@ class Response extends \Hyperf\HttpMessage\Base\Response
/* /*
* Cookies * Cookies
*/ */
foreach ((array)$this->cookies as $domain => $paths) { foreach ((array) $this->cookies as $domain => $paths) {
foreach ($paths ?? [] as $path => $item) { foreach ($paths ?? [] as $path => $item) {
foreach ($item ?? [] as $name => $cookie) { foreach ($item ?? [] as $name => $cookie) {
if ($cookie instanceof Cookie) { if ($cookie instanceof Cookie) {

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://doc.hyperf.io
* @contact group@hyperf.io
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
*/
namespace Hyperf\HttpMessage\Stream;
interface FileInterface
{
public function getFilename(): string;
}

View File

@ -12,11 +12,10 @@ declare(strict_types=1);
namespace Hyperf\HttpMessage\Stream; namespace Hyperf\HttpMessage\Stream;
use Psr\Http\Message\StreamInterface;
use InvalidArgumentException; use InvalidArgumentException;
use Psr\Http\Message\StreamInterface;
class SwooleFileStream implements StreamInterface class SwooleFileStream implements StreamInterface, FileInterface
{ {
/** /**
* @var string * @var string
@ -31,15 +30,15 @@ class SwooleFileStream implements StreamInterface
/** /**
* SwooleFileStream constructor. * SwooleFileStream constructor.
* *
* @param string $file_path * @param string $file
*/ */
public function __construct(string $file_path) public function __construct(string $file)
{ {
if (!file_exists($file_path)) { if (! file_exists($file)) {
throw new InvalidArgumentException('Not a file'); throw new InvalidArgumentException('Not a file');
} }
$this->contents = $file_path; $this->contents = $file;
$this->size = filesize($file_path); $this->size = filesize($file);
} }
/** /**
@ -88,7 +87,7 @@ class SwooleFileStream implements StreamInterface
*/ */
public function getSize() public function getSize()
{ {
if (!$this->size) { if (! $this->size) {
$this->size = filesize($this->getContents()); $this->size = filesize($this->getContents());
} }
return $this->size; return $this->size;
@ -97,8 +96,8 @@ class SwooleFileStream implements StreamInterface
/** /**
* Returns the current position of the file read/write pointer. * Returns the current position of the file read/write pointer.
* *
* @return int Position of the file pointer
* @throws \RuntimeException on error * @throws \RuntimeException on error
* @return int Position of the file pointer
*/ */
public function tell() public function tell()
{ {
@ -170,8 +169,8 @@ class SwooleFileStream implements StreamInterface
* Write data to the stream. * Write data to the stream.
* *
* @param string $string the string that is to be written * @param string $string the string that is to be written
* @return int returns the number of bytes written to the stream
* @throws \RuntimeException on failure * @throws \RuntimeException on failure
* @return int returns the number of bytes written to the stream
*/ */
public function write($string) public function write($string)
{ {
@ -194,9 +193,9 @@ class SwooleFileStream implements StreamInterface
* @param int $length Read up to $length bytes from the object and return * @param int $length Read up to $length bytes from the object and return
* them. Fewer than $length bytes may be returned if underlying stream * them. Fewer than $length bytes may be returned if underlying stream
* call returns fewer bytes. * call returns fewer bytes.
* @throws \RuntimeException if an error occurs
* @return string returns the data read from the stream, or an empty string * @return string returns the data read from the stream, or an empty string
* if no bytes are available * if no bytes are available
* @throws \RuntimeException if an error occurs
*/ */
public function read($length) public function read($length)
{ {
@ -206,9 +205,9 @@ class SwooleFileStream implements StreamInterface
/** /**
* Returns the remaining contents in a string. * Returns the remaining contents in a string.
* *
* @return string
* @throws \RuntimeException if unable to read or an error occurs while * @throws \RuntimeException if unable to read or an error occurs while
* reading * reading
* @return string
*/ */
public function getContents() public function getContents()
{ {
@ -230,4 +229,9 @@ class SwooleFileStream implements StreamInterface
{ {
throw new \BadMethodCallException('Not implemented'); throw new \BadMethodCallException('Not implemented');
} }
public function getFilename(): string
{
return $this->getContents();
}
} }

View File

@ -13,8 +13,8 @@ declare(strict_types=1);
namespace Hyperf\HttpServer; namespace Hyperf\HttpServer;
use BadMethodCallException; use BadMethodCallException;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpMessage\Stream\SwooleFileStream; use Hyperf\HttpMessage\Stream\SwooleFileStream;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\ResponseInterface; use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\HttpServer\Exception\Http\EncodingException; use Hyperf\HttpServer\Exception\Http\EncodingException;
use Hyperf\Utils\ApplicationContext; use Hyperf\Utils\ApplicationContext;
@ -112,36 +112,20 @@ class Response implements PsrResponseInterface, ResponseInterface
} }
/** /**
* Automatically sets the ETag header according to the checksum of the file. * @param string $file
* @param string $filePath
* @param bool $weak
* @return string
*/
protected function autoEtag(string $filePath, $weak = false): string
{
$etag = sha1_file($filePath);
if (0 !== strpos($etag, '"')) {
$etag = '"' . $etag . '"';
}
return (true === $weak ? 'W/' : '') . $etag;
}
/**
* @param string $pathToFile
* @param string $name * @param string $name
* @return PsrResponseInterface * @return PsrResponseInterface
*/ */
public function download(string $pathToFile, string $name = ''): PsrResponseInterface public function download(string $file, string $name = ''): PsrResponseInterface
{ {
$filename = $name ?: basename($pathToFile); $filename = $name ?: basename($file);
return $this->withHeader('Content-Description', 'File Transfer') return $this->withHeader('Content-Description', 'File Transfer')
->withHeader('Content-Type', 'application/octet-stream') ->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', "attachment; filename={$filename}") ->withHeader('Content-Disposition', "attachment; filename={$filename}")
->withHeader('Content-Transfer-Encoding', 'binary') ->withHeader('Content-Transfer-Encoding', 'binary')
->withHeader('Pragma', 'public') ->withHeader('Pragma', 'public')
->withHeader('ETag', $this->autoEtag($pathToFile)) ->withHeader('ETag', $this->etag($file))
->withBody(new SwooleFileStream($pathToFile)); ->withBody(new SwooleFileStream($file));
} }
/** /**
@ -378,6 +362,21 @@ class Response implements PsrResponseInterface, ResponseInterface
return $this->getResponse()->getReasonPhrase(); return $this->getResponse()->getReasonPhrase();
} }
/**
* Get ETag header according to the checksum of the file.
* @param string $file
* @param bool $weak
* @return string
*/
protected function etag(string $file, $weak = false): string
{
$etag = sha1_file($file);
if (strpos($etag, '"') !== 0) {
$etag = '"' . $etag . '"';
}
return ($weak === true ? 'W/' : '') . $etag;
}
/** /**
* @param array|Arrayable|Jsonable $data * @param array|Arrayable|Jsonable $data
* @throws EncodingException when the data encoding error * @throws EncodingException when the data encoding error