来自 Digital ocean spaces 的 Laravel 存储流文件的性能

Performance of Laravel storage streaming file from Digital ocean spaces

我通过搜索主题获得了以下代码

Route::get('/test', function () {
    //disable execution time limit when downloading a big file.
    set_time_limit(0);

    $fs = Storage::disk('local');

    $path = 'uploads/user-1/1653600850867.mp3';

    $stream = $fs->readStream($path);

    if (ob_get_level()) ob_end_clean();

    return response()->stream(function () use ($stream) {
        fpassthru($stream);
    },
        200,
        [
            'Accept-Ranges' => 'bytes',
            'Content-Length' => 14098560,
            'Content-Type' => 'application/octet-stream',
        ]);
});

但是,当我在 UI 上单击播放时,需要四秒钟才能开始播放。如果我将磁盘切换到本地,它几乎可以立即播放。

有没有办法提高性能,或者根据请求按范围读取流?

编辑

我目前的 DO 配置如下

            'driver' => 's3',
            'key' => env('DO_ACCESS_KEY_ID'),
            'secret' => env('DO_SECRET_ACCESS_KEY'),
            'region' => env('DO_DEFAULT_REGION'),
            'bucket' => env('DO_BUCKET'),
            'url' => env('DO_URL'),
            'endpoint' => env('DO_ENDPOINT'),
            'use_path_style_endpoint' => env('DO_USE_PATH_STYLE_ENDPOINT', false),

但我发现有两种在线集成,一种指定 CDN 端点,另一种不指定。我不确定哪个是相关的,尽管指定 CDN 的是 Laravel 8 而我在 Laravel 9.

我不得不更改我的代码:

  1. 我不得不使用 php SDK 客户端连接到 Aws,因为 Laravel API 不灵活,无法传递额外的参数(至少我还没有找到研究时的任何事情)
  2. 更改为 streamDownload,因为我在文档中看不到任何对流方法的描述,尽管它存在于代码中。

所以下面的代码可以实现我的目标,即根据请求中收到的范围按块下载。

    return response()->streamDownload(function(){
        $client = new Aws\S3\S3Client([
            'version' => 'latest',
            'region'  =>  config('filesystems.disks.do.region'),
            'endpoint' =>  config('filesystems.disks.do.endpoint'),
            'credentials' => [
                'key'    => config('filesystems.disks.do.key'),
                'secret' => config('filesystems.disks.do.secret'),
            ],
        ]);

        $path = 'uploads/user-1/1653600850867.mp3';

        $range = request()->header('Range');

        $result = $client->getObject([
            'Bucket' => 'wyxos-streaming',
            'Key' => $path,
            'Range' => $range
        ]);

        echo $result['Body'];
    },
        200,
        [
            'Accept-Ranges' => 'bytes',
            'Content-Length' => 14098560,
            'Content-Type' => 'application/octet-stream',
        ]);

注:

  • 在实际场景中,如果未指定范围,则需要满足内容长度需要为实际文件大小
  • 然而,当存在范围时,内容长度应该是被回显的段的大小