0

I have the following function in my FileController that retrieves a video from my storage (local):

function getVideo() {

    $video = Storage::disk('local')->get("uploads/map_name/name_of_video.mp4");
    $response = Response::make( $video, 200 );
    $response->header( 'Content-Type', 'video/mp4' );

    return $response;
}

In my web.php i have the following route:

Route::get('/get-video/', 'FileController@getVideo')->name('get-video');

Last, in my view, i have the following:

<video controls>

    <source src="{{ route('get-video') }}" type="video/mp4">
    Your browser does not support the video tag.

</video>

This works fine. The video is shown in my view. However, i would like to make this function dynamic but i can't seem to get this working. I have made the following changes:

First, i passed a var to the getVideo function and pass it to the get function:

function getVideo($video_name) {

    $video = Storage::disk('local')->get("uploads/{$video_name}");
    $response = Response::make( $video, 200 );
    $response->header( 'Content-Type', 'video/mp4' );

    return $response;
}

Then, i changed the route to take a var:

Route::get('/get-video/{video_name}', 'FileController@getVideo')->name('get-video');

And finally, in my view, i pass the var to the route

<video controls>

    <source src="{{ route('get-video', ['video_name' => '/map_name/name_of_video.mp4']) }}" type="video/mp4">
    Your browser does not support the video tag.

</video>

This, however, results in a 404 not found. I get this route: https://mysite.local/get-video/map_name/name_of_video.mp4.

Notice that the /upload part doesn't get rendered. However, if i add this manually, the route fails as well.

I already did the php artisan storage:link as well.

Sidenote: the /map_name/name_of_video.mp4 part is something I can retrieve from the database for each video.

El Klo
  • 173
  • 3
  • 14
  • 1
    A little more off-topic but a few remarks I did want to leave for future research / improvements to your code: - Make sure users cannot access video's (or possibly other files stored) they shouldn't by checking the filename against a record in your database for example. - Research about streaming the file back to the user instead of using `get` and making it into a response since that will load the whole file in memory which can cause issues with large files. See also: https://stackoverflow.com/a/29747052/1580028 – Alex Jul 05 '19 at 11:36
  • I will look into this! Thanks a lot. – El Klo Jul 05 '19 at 11:51

1 Answers1

1

This has to do with you using a / character in the route parameter which by default does not work because that is a separator symbol used to separate route parameters.

You can try and define the route like the following to overcome that:

Route::get('/get-video/{video_name}', 'FileController@getVideo')->name('get-video')->where('video_name', '(.*)');

The in the where you can define a regex that matches the route parameter, in this case .* matches everything that comes after /get-video/.

You can than use it like:

{{ route('get-video', ['video_name' => 'map_name/name_of_video.mp4']) }}

Not I removed the leading / in the route example to prevent a duplicated / character in the path.

Alex
  • 1,425
  • 11
  • 25