1

I am using spatie library to upload some files which will be saved to the storage folder. What I want to accomplished at the moment, is to view those files or images when I am an authenticated user. I've tried creating a symlink using this command ,

php artisan storage:link

But this makes those file to be seen publicly. What I only want is to view those file, only when the user is an authenticated user. So far this is what I did but it seems like I miss something.

ROUTE :

Route::get('/storage/{filePath}', 'ComplaintsController@fileStorageServe')->where(['filePath' => '.*'])->name('complaints.viewfile');

CONTROLLER :

public function fileStorageServe($file) {
    // know you can have a mapping so you dont keep the sme names as in local (you can not precsise the same structor as the storage, you can do anything)

    // any permission handling or anything else

    // we check for the existing of the file 
    if (!Storage::disk('local')->exists($filePath)){ // note that disk()->exists() expect a relative path, from your disk root path. so in our example we pass directly the path (/.../laravelProject/storage/app) is the default one (referenced with the helper storage_path('app')
        abort('404'); // we redirect to 404 page if it doesn't exist
    } 
    //file exist let serve it 

    // if there is parameters [you can change the files, depending on them. ex serving different content to different regions, or to mobile and desktop ...etc] // repetitive things can be handled through helpers [make helpers]

    return response()->file(storage_path('app'.DIRECTORY_SEPARATOR.($filePath))); // the response()->file() will add the necessary headers in our place (no headers are needed to be provided for images (it's done automatically) expected hearder is of form => ['Content-Type' => 'image/png'];

    // big note here don't use Storage::url() // it's not working correctly.  
}

VIEW :

@foreach($complaint->attachments as $attachment)
  <a href="{{url('complaints.viewfile', $attachment->getUrl())}}" target="_blank">{{ $attachment->file_name }}</a>
@endforeach

When I click the link it will give me something like this.

http://127.0.0.1:8000/complaints.viewfile/http%3A%2F%2F127.0.0.1%3A8000%2Fstorage%2F3%2F60580fdeadc55_worship.jpg

Please help. Thank you...

apokryfos
  • 38,771
  • 9
  • 70
  • 114
Hope
  • 644
  • 2
  • 6
  • 21

2 Answers2

1

You need to understand how files are served by a web server and how that interacts with a laravel application.

You likely have nginx or apache set up to serve files from the public folder of your laravel app. ie: /var/www/sites/laravel-site/public.

When an HTTP request is sent to your server, if your nginx or apache is configured to serve files like laravel-site.com/storage/documents/secrets.pdf statically, then your laravel application code will never even be run, and you cannot control access to these files at the application level.

If you want to setup access control to files, you will need to first ensure the requests are not going to be served statically, and second setup a route to serve the files after checking if the user/request has permission to access the file(s) you want to serve.

There are lots of other great answers and resources on how to do this.

Kurt Friars
  • 3,625
  • 2
  • 16
  • 29
  • thanks mate. I've tried adding some your suggested answer but it seems I miss something. Can you please give your idea about this ? – Hope Mar 22 '21 at 08:45
  • when I used the route method, it will give me this error. Route [complaints.viewfile] not defined. Why is that ? I used it inside my anchor tag. – Hope Mar 22 '21 at 08:53
  • @Hope you are getting well outside the scope of your question. Please ask a new question if you cannot solve your issue. Also, please delete the debugging comments above :) – Kurt Friars Mar 22 '21 at 09:04
-2

Correct me if im wrong but isn't the easiest way to do that via system-settings ? Like you have different Users and you just put them in different groups that have different rights for folders/files.