mirror of
https://github.com/koel/koel
synced 2024-09-20 14:21:55 +00:00
Use a proper package for php streamer
This commit is contained in:
parent
2349a66a31
commit
37ec4aaa6f
6 changed files with 80 additions and 98 deletions
|
@ -5,6 +5,7 @@ namespace App\Services;
|
|||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use InvalidArgumentException;
|
||||
use Log;
|
||||
use SimpleXMLElement;
|
||||
|
||||
/**
|
||||
|
@ -67,7 +68,9 @@ abstract class ApiClient
|
|||
|
||||
return $body;
|
||||
} catch (ClientException $e) {
|
||||
return;
|
||||
Log::error($e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,6 +217,7 @@ class FileSynchronizer
|
|||
// But if 'album' isn't specified, we don't want to update normal albums.
|
||||
// This variable is to keep track of this state.
|
||||
$changeCompilationAlbumOnly = false;
|
||||
|
||||
if (in_array('compilation', $tags, true) && !in_array('album', $tags, true)) {
|
||||
$tags[] = 'album';
|
||||
$changeCompilationAlbumOnly = true;
|
||||
|
@ -261,7 +262,7 @@ class FileSynchronizer
|
|||
*
|
||||
* @param mixed[]|null $coverData
|
||||
*/
|
||||
private function generateAlbumCover(Album $album, ?array $coverData)
|
||||
private function generateAlbumCover(Album $album, ?array $coverData): void
|
||||
{
|
||||
// If the album has no cover, we try to get the cover image from existing tag data
|
||||
if ($coverData) {
|
||||
|
|
|
@ -2,104 +2,39 @@
|
|||
|
||||
namespace App\Services\Streamers;
|
||||
|
||||
use DaveRandom\Resume\FileResource;
|
||||
use function DaveRandom\Resume\get_request_header;
|
||||
use DaveRandom\Resume\InvalidRangeHeaderException;
|
||||
use DaveRandom\Resume\NonExistentFileException;
|
||||
use DaveRandom\Resume\RangeSet;
|
||||
use DaveRandom\Resume\Resource;
|
||||
use DaveRandom\Resume\ResourceServlet;
|
||||
use DaveRandom\Resume\SendFileFailureException;
|
||||
use DaveRandom\Resume\UnreadableFileException;
|
||||
use DaveRandom\Resume\UnsatisfiableRangeException;
|
||||
|
||||
class PHPStreamer extends Streamer implements DirectStreamerInterface
|
||||
{
|
||||
/**
|
||||
* Stream the current song using the most basic PHP method: readfile()
|
||||
* Credits: DaveRandom @ http://stackoverflow.com/a/4451376/794641.
|
||||
*/
|
||||
public function stream(): void
|
||||
public function stream()
|
||||
{
|
||||
$range = $this->getRange();
|
||||
$start = null;
|
||||
$end = null;
|
||||
$fileSize = filesize($this->song->path);
|
||||
|
||||
if ($range) {
|
||||
list($param, $range) = explode('=', $range);
|
||||
|
||||
// Bad request - range unit is not 'bytes'
|
||||
abort_unless(strtolower(trim($param)) === 'bytes', 400);
|
||||
|
||||
$range = explode(',', $range);
|
||||
$range = explode('-', $range[0]); // We only deal with the first requested range
|
||||
|
||||
// Bad request - 'bytes' parameter is not valid
|
||||
abort_unless(count($range) === 2, 400);
|
||||
|
||||
$start = (int) $range[0];
|
||||
|
||||
if (!$range[0]) {
|
||||
// First number missing, return last $range[1] bytes
|
||||
$end = (int) $range[1];
|
||||
} elseif (!$range[1]) {
|
||||
$end = $fileSize - 1;
|
||||
} else {
|
||||
// Both numbers present, return specific range
|
||||
$end = (int) $range[1];
|
||||
|
||||
if ($end >= $fileSize) {
|
||||
$end = $fileSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
$partial = $start > 0 || $end < $fileSize - 1;
|
||||
$length = $end - $start + 1;
|
||||
} else {
|
||||
$length = filesize($this->song->path);
|
||||
$partial = false;
|
||||
}
|
||||
|
||||
// Send standard headers
|
||||
header("Content-Type: {$this->contentType}");
|
||||
header("Content-Length: $length");
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($this->song->path)));
|
||||
header('Content-Disposition: attachment; filename="' . basename($this->song->path) . '"');
|
||||
header('Accept-Ranges: bytes');
|
||||
|
||||
// if requested, send extra headers and part of file...
|
||||
if ($partial) {
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
header("Content-Range: bytes $start-$end/$fileSize");
|
||||
|
||||
// Error out if we can't read the file
|
||||
abort_unless($fp = fopen($this->song->path, 'r'), 500);
|
||||
|
||||
if ($start) {
|
||||
fseek($fp, $start);
|
||||
}
|
||||
|
||||
while ($length) {
|
||||
// Read in blocks of 8KB so we don't chew up memory on the server
|
||||
$read = ($length > 8192) ? 8192 : $length;
|
||||
$length -= $read;
|
||||
echo fread($fp, $read);
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
} else {
|
||||
readfile($this->song->path);
|
||||
try {
|
||||
$rangeSet = RangeSet::createFromHeader(get_request_header('Range'));
|
||||
/** @var Resource $resource */
|
||||
$resource = new FileResource($this->song->path, 'application/octet-stream');
|
||||
(new ResourceServlet($resource))->sendResource($rangeSet);
|
||||
} catch (InvalidRangeHeaderException $e) {
|
||||
abort(400);
|
||||
} catch (UnsatisfiableRangeException $e) {
|
||||
abort(416);
|
||||
} catch (NonExistentFileException $e) {
|
||||
abort(404);
|
||||
} catch (UnreadableFileException $e) {
|
||||
abort(500);
|
||||
} catch (SendFileFailureException $e) {
|
||||
abort_unless(headers_sent(), 500);
|
||||
echo "An error occurred while attempting to send the requested resource: {$e->getMessage()}";
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
private function getRange():? string
|
||||
{
|
||||
if (getenv('HTTP_RANGE')) {
|
||||
// IIS/Some Apache versions
|
||||
return (string) getenv('HTTP_RANGE');
|
||||
}
|
||||
|
||||
if (function_exists('apache_request_headers') && $apache = apache_request_headers()) {
|
||||
// Try Apache again
|
||||
foreach ($apache as $header => $val) {
|
||||
if (strtolower($header) === 'range') {
|
||||
return (string) $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class YouTubeService extends ApiClient implements ApiConsumerInterface
|
|||
public function search(string $q, string $pageToken = '', int $perPage = 10)
|
||||
{
|
||||
if (!$this->enabled()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
$uri = sprintf('search?part=snippet&type=video&maxResults=%s&pageToken=%s&q=%s',
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
"ext-json": "*",
|
||||
"ext-SimpleXML": "*",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"barryvdh/laravel-cors": "^0.11.0"
|
||||
"barryvdh/laravel-cors": "^0.11.0",
|
||||
"daverandom/resume": "^0.0.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"filp/whoops": "~2.0",
|
||||
|
|
44
composer.lock
generated
44
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "b86ba223f580a260b9be10b3f8ad6856",
|
||||
"content-hash": "6a60d98d33aca16675ba28fe3b3adfb9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
|
@ -255,6 +255,48 @@
|
|||
],
|
||||
"time": "2018-01-04T06:59:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "daverandom/resume",
|
||||
"version": "v0.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DaveRandom/Resume.git",
|
||||
"reference": "3d1c11b6c4315dd8d25d6f567c5ea392c7c60edb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DaveRandom/Resume/zipball/3d1c11b6c4315dd8d25d6f567c5ea392c7c60edb",
|
||||
"reference": "3d1c11b6c4315dd8d25d6f567c5ea392c7c60edb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DaveRandom\\Resume\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"mit"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Wright",
|
||||
"email": "me@daverandom.com"
|
||||
}
|
||||
],
|
||||
"description": "Tiny library to facilitate resumable downloads",
|
||||
"time": "2018-01-28T03:18:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "v1.8.0",
|
||||
|
|
Loading…
Reference in a new issue