CopyPastor

Detecting plagiarism made easy.

Score: 0.8458430171012878; Reported for: String similarity Open both answers

Possible Plagiarism

Plagiarized on 2022-06-01
by Scorekaj22

Original Post

Original - Posted on 2018-10-01
by Jmorko



            
Present in both answers; Present only in the new answer; Present only in the old answer;

After researching quite a bit I realized that the issue came down to updates described here `https://laravel.com/docs/9.x/upgrade#flysystem-3`
I ended up altering the code a bit where I use environment variables to fill out what was before provieded by the adapter in the code.
In the latest version of the flysystem there is no longer access to the client via the adapter and this was what broke the service.
For a fully working class then you can use below for laravel 9
<?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; } }

I personally am opposed to the idea of redirecting to an S3 URL. I mask all my URLs through a Laravel php wrapper server-side. This is the code I use to do so if anyone else encounters similar issues. This code is written for streaming a video from S3 with Laravel 5.6 (and includes HTTP_RANGE support so it works on iOS too).

I use the class below, placed at App/Http/Responses. To use this class, create a method that does this (this is like a getFile method):
$filestream = new \App\Http\Responses\S3FileStream('file_path_and_name_within_bucket', 'disk_bucket_name', 'output_file_name_when_downloaded'); return $filestream->output();
With any luck, you should be streaming in no time (without revealing an S3 URL)!


**S3FileStream.php:** <?php
namespace Http\Responses;
use Exception; use Illuminate\Filesystem\FilesystemAdapter; use Illuminate\Http\Response; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Storage; use Symfony\Component\HttpFoundation\StreamedResponse;
class S3FileStream { /** * @var \League\Flysystem\AwsS3v3\AwsS3Adapter */ private $adapter;
/** * 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 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) { $this->filePath = $filePath; $this->adapterName = $adapter; $this->disk = Storage::disk($this->adapterName); $this->adapter = $this->disk->getAdapter(); $this->humanName = $humanName; //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->adapter->getClient()->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->adapter->getBucket()}/{$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; } }


        
Present in both answers; Present only in the new answer; Present only in the old answer;