首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Laravel 9: AWS S3将视频撤回到流中

Laravel 9: AWS S3将视频撤回到流中
EN

Stack Overflow用户
提问于 2022-05-30 10:51:35
回答 2查看 515关注 0票数 2

在用PHP8.1.4更新到Laravel9.14之后,流就打破了基于这个答案的https://stackoverflow.com/a/52598361/6825499

我看得出这是因为

代码语言:javascript
运行
复制
Call to undefined method League\Flysystem\AwsS3V3\AwsS3V3Adapter::getClient()

因此,它似乎已从联盟/飞行系统的最新版本-AWS-S3-v3 (3.0.13)中删除。

我确实找到了这篇文章的参考,它试图解释现在有一个解决办法:从Laravel 9的存储立面获取S3Client

虽然这件事太复杂了,我无法理解。

有人知道能做些什么吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-06-01 19:01:41

经过大量的研究,我意识到这个问题归结为关于升级的Laravel文档页面中描述的更新。

最后,我修改了代码,使用环境变量来填充代码中适配器提供的内容。

在最新版本的flysystem中,不再可以通过适配器访问客户端。由于上述原因,服务中断了。

对于一个完全工人阶级,那么您可以使用下面的代码为laravel版本9

代码语言:javascript
运行
复制
    <?php
    namespace App\Http;
    
    use Exception;
    use Illuminate\Filesystem\FilesystemAdapter;
    use Illuminate\Http\Response;
    use Illuminate\Support\Arr;
    use Illuminate\Support\Str;
    use League\Flysystem\Filesystem;
    use Storage;
    use Symfony\Component\HttpFoundation\StreamedResponse;
    
    class S3FileStream
    {
        /**
         * Name of adapter
         *
         * @var string
         */
        private $adapterName;
    
        /**
         * Storage disk
         *
         * @var FilesystemAdapter
         */
        private $disk;
    
        /**
         * @var int file end byte
         */
        private $end;
    
        /**
         * @var string
         */
        private $filePath;
    
        /**
         * Human-known filename
         *
         * @var string|null
         */
        private $humanName;
    
        /**
         * @var bool storing if request is a range (or a full file)
         */
        private $isRange = false;
    
        /**
         * @var int|null length of bytes requested
         */
        private $length = null;
    
        /**
         * @var array
         */
        private $returnHeaders = [];
    
        /**
         * @var int file size
         */
        private $size;
    
    /**
         * @var string bucket name
         */
        private $bucket;
    
        /**
         * @var int start byte
         */
        private $start;
    
        /**
         * S3FileStream constructor.
         * @param string $filePath
         * @param string $adapter
         * @param string $humanName
         */
        public function __construct(string $filePath, string $adapter = 's3', ?string $humanName = null)
        {
            $options = [
        'region'            => env("AWS_DEFAULT_REGION"),
        'version'           => 'latest'
    ];
            $this->filePath    = $filePath;
            $this->adapterName = $adapter;
            $this->disk        = Storage::disk($this->adapterName);
            $this->client     = new \Aws\S3\S3Client($options);
            $this->humanName   = $humanName;
            $this->bucket      = env("AWS_BUCKET");
            //Set to zero until setHeadersAndStream is called
            $this->start = 0;
            $this->size  = 0;
            $this->end   = 0;
        }
    
        /**
         * Output file to client.
         */
        public function output()
        {
            return $this->setHeadersAndStream();
        }
    
        /**
         * Output headers to client.
         * @return Response|StreamedResponse
         */
        protected function setHeadersAndStream()
        {
            if (!$this->disk->exists($this->filePath)) {
                report(new Exception('S3 File Not Found in S3FileStream - ' . $this->adapterName . ' - ' . $this->disk->path($this->filePath)));
                return response('File Not Found', 404);
            }
    
            $this->start   = 0;
            $this->size    = $this->disk->size($this->filePath);
            $this->end     = $this->size - 1;
            $this->length  = $this->size;
            $this->isRange = false;
    
            //Set headers
            $this->returnHeaders = [
                'Last-Modified'       => $this->disk->lastModified($this->filePath),
                'Accept-Ranges'       => 'bytes',
                'Content-Type'        => $this->disk->mimeType($this->filePath),
                'Content-Disposition' => 'inline; filename=' . ($this->humanName ?? basename($this->filePath) . '.' . Arr::last(explode('.', $this->filePath))),
                'Content-Length'      => $this->length,
            ];
    
            //Handle ranges here
            if (!is_null(request()->server('HTTP_RANGE'))) {
                $cStart = $this->start;
                $cEnd   = $this->end;
    
                $range = Str::after(request()->server('HTTP_RANGE'), '=');
                if (strpos($range, ',') !== false) {
                    return response('416 Requested Range Not Satisfiable', 416, [
                        'Content-Range' => 'bytes */' . $this->size,
                    ]);
                }
                if (substr($range, 0, 1) == '-') {
                    $cStart = $this->size - intval(substr($range, 1)) - 1;
                } else {
                    $range  = explode('-', $range);
                    $cStart = intval($range[0]);
    
                    $cEnd = (isset($range[1]) && is_numeric($range[1])) ? intval($range[1]) : $cEnd;
                }
    
                $cEnd = min($cEnd, $this->size - 1);
                if ($cStart > $cEnd || $cStart > $this->size - 1) {
                    return response('416 Requested Range Not Satisfiable', 416, [
                        'Content-Range' => 'bytes */' . $this->size,
                    ]);
                }
    
                $this->start                           = intval($cStart);
                $this->end                             = intval($cEnd);
                $this->length                          = min($this->end - $this->start + 1, $this->size);
                $this->returnHeaders['Content-Length'] = $this->length;
                $this->returnHeaders['Content-Range']  = 'bytes ' . $this->start . '-' . $this->end . '/' . $this->size;
                $this->isRange                         = true;
            }
    
            return $this->stream();
        }
    
        /**
         * Stream file to client.
         * @throws Exception
         * @return StreamedResponse
         */
        protected function stream(): StreamedResponse
        {
            $this->client->registerStreamWrapper();
            // Create a stream context to allow seeking
            $context = stream_context_create([
                's3' => [
                    'seekable' => true,
                ],
            ]);
            // Open a stream in read-only mode
            if (!($stream = fopen("s3://{$this->bucket}/{$this->filePath}", 'rb', false, $context))) {
                throw new Exception('Could not open stream for reading export [' . $this->filePath . ']');
            }
            if (isset($this->start) && $this->start > 0) {
                fseek($stream, $this->start, SEEK_SET);
            }
    
            $remainingBytes = $this->length ?? $this->size;
            $chunkSize      = 100;
    
            $video = response()->stream(
                function () use ($stream, $remainingBytes, $chunkSize) {
                    while (!feof($stream) && $remainingBytes > 0) {
                        $toGrab = min($chunkSize, $remainingBytes);
                        echo fread($stream, $toGrab);
                        $remainingBytes -= $toGrab;
                        flush();
                    }
                    fclose($stream);
                },
                ($this->isRange ? 206 : 200),
                $this->returnHeaders
            );
    
            return $video;
        }
    }
票数 0
EN

Stack Overflow用户

发布于 2022-05-30 12:05:39

您需要将服务器上的PHP版本更新为最新版本。听起来服务器还在PHP7.x版本上,这就是问题所在。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72433129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档