为什么要这样搞 因为很多视频 不可能 一次传输 需要切片 不然会断流
用nginx 就不会有这个问题 这个是 原生方案
中间件实现
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace app\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* Class StaticFile
* @package app\middleware
*/
class StaticFile implements MiddlewareInterface
{
public function process(Request $request, callable $next): Response
{
$path = ltrim($request->path(), '/');
$public_dir = config('app.public_path');
$file = $public_dir . '/' . $path;
//不是文件 不需要 这个中间件处理
if (!is_file($file)) return $next($request);
// 禁止隐藏文件
if (strpos($path, '/.') !== false) {
return new Response(403, [], '<h1>403 forbidden</h1>');
}
$mime_type = mime_content_type($file) ?: 'application/octet-stream';//文件类型
//如果浏览器要切片 就返回切片内容
// 解析 Range
$range_header = $request->header('Range', '');
if(!empty($range_header)){
$size = filesize($file);//文件大小
//大文件切片返回 这个是针对视频传输的
$start = 0;
$end = $size - 1;
if (preg_match('/bytes=(\d+)-(\d*)/', $range_header, $matches)) {
$start = intval($matches[1]);
if ($matches[2] !== '') {
$end = intval($matches[2]);
}
}
// ⭐ 固定每次发送的最大大小
$max_chunk = 5 * 1024 * 1024; // 5MB
if (($end - $start + 1) > $max_chunk) {
$end = $start + $max_chunk - 1;
if ($end >= $size) $end = $size - 1;
}
$length = $end - $start + 1;
$fp = fopen($file, 'rb');
fseek($fp, $start);
$body = fread($fp, $length);
fclose($fp);
return new Response(
206, // Partial Content
[
'Content-Type' => $mime_type,
'Accept-Ranges' => 'bytes',
'Content-Range' => "bytes $start-$end/$size",
'Connection' => 'keep-alive',
],
$body
);
}
//返回文件内容
return new Response(
200, // Partial Content
[
'Content-Type' => $mime_type,
'Accept-Ranges' => 'bytes',
'Connection' => 'keep-alive',
],
file_get_contents($file)
);
}
}
配置文件 需要修改
config->static
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Static file settings
*/
return [
'enable' => true,
'middleware' => [// Static file Middleware
app\middleware\StaticFile::class,
],
];
点赞,很合适内部文件存储