如何处理laravel 5中的私人图像?

时间:2015-02-17 13:44:28

标签: laravel laravel-5

我是Laravel的新手并尝试存储私有图像,以便只有经过身份验证的用户才能访问它们。首先,我将图像存储在Public / UserImages文件夹中。但是这里所有图片都可供未经身份验证的用户访问,也可以访问Inspect Element of chrome然后更改用户ID。请帮助我...

4 个答案:

答案 0 :(得分:10)

这真的取决于你。它必须位于public目录之外 - 我亲自挑选resources/uploadsstorage/uploads,或使用cloud filesystem support完全将其存储在服务器之外

无论您选择什么,您都需要一个获取文件的路径,并在首次检查他们有权访问后将其传递给用户。

答案 1 :(得分:9)

以下是我如何解决在Laravel 5中存储图像的问题,以便只有经过身份验证的用户才能查看图像。未经过身份验证的人员将被定向到登录页面。我的服务器是Ubuntu / Apache2服务器。

  1. 创建目录/ var / www / YOURWEBSITE / app / Assets / Images

  2. 添加路线到app / Http / routes.php。

    Route::get('/images/{file}','ImageController@getImage');

  3. 创建一个控制器app / Http / Controllers / ImageController.php

    <?php
    namespace App\Http\Controllers;
    
    use App\Http\Requests;
    
    use App\Http\Controllers\Controller;
    
    use Illuminate\Http\Request;
    
    use Auth;
    
    class ImageController extends Controller {
    
        public function __construct()
       {
            $this->middleware('auth');
       } 
        public function getImage($filename) {
           $path = '/var/www/YOURWEBSITE/app/Assets/Images/'.$filename;
           $type = "image/jpeg";
           header('Content-Type:'.$type);
           header('Content-Length: ' . filesize($path));
           readfile($path);
    
        }
    
     }
    
  4. 在您的视图中,您有img标签:

    src="{{ url('/images/test.jpg') }}"
    
  5. 这当然假设test.jpg是/ var / www / YOURWEBSITE / app / Assets / Images /

    中的文件

    您当然可以添加更多逻辑,例如不对图像路径进行硬编码等。这只是一个强制执行身份验证的简单示例。请注意在控制器构造函数中使用中间件(&#39; auth&#39;)。

答案 2 :(得分:6)

几天前我遇到了同样的问题并提出了这个解决方案:

  1. 您要做的第一件事就是将文件上传到非公共目录。我的应用程序正在存储已扫描的发票,因此我将把它们放在storage/app/invoices内。上传文件和生成网址的代码如下:

    // This goes inside your controller method handling the POST request.
    
    $path = $request->file('invoice')->store('invoices');
    $url = env('APP_URL') . Illuminate\Support\Facades\Storage::url($path);
    

    返回的网址应该会产生类似http://yourdomain.com/storage/invoices/uniquefilename.jpg

  2. 的内容
  3. 现在您必须创建一个使用auth middleware的控制器,以确保用户通过身份验证。然后,定义一个从私有目录中获取文件并将其作为文件响应返回的方法。那将是:

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Support\Facades\Storage;
    
    class FileController extends Controller
    {
    
        public function __construct()
        {
            $this->middleware('auth');
        }
    
        public function __invoke($file_path)
        {
            if (!Storage::disk('local')->exists($file_path)) {
                abort(404);
            }
    
            $local_path = config('filesystems.disks.local.root') . DIRECTORY_SEPARATOR . $file_path;
    
            return response()->file($local_path);
        }
    }
    
  4. 最后一件事是在routes/web.php文件中注册路线:

    Route::get('/storage/{file_name}', 'FileController')->where(['file_name' => '.*'])
    
  5. 所以你有它,一个非常可重复使用的片段,用于处理私人文件的所有项目:)

答案 3 :(得分:3)

如何在Laravel 5.7中做到这一点

要拥有私有文件(图像),您需要通过 route =>控制器流来提供文件。并且您的身份验证中间件将处理身份验证和权限。如果需要进一步的授权,请在控制器中进行处理。

所以首先我们设置一条路线:

在这里,我们可以采用一种途径来处理所有文件 [我个人不希望这样做]。 我们可以使用这样的路由来做到这一点(就像通配符一样。)

Route::get('/storage/{filePath}', 'FileController@fileStorageServe')
->where(['filePath' => '.*'])

您也可以这样命名:

Route::get('/storage/{fileName}', 'FileController@fileStorageServe')
->where(['fileName' => '.*'])->name('storage.gallery.file');

否则,我们为每种类型/类型的文件创建路由:(优势:您将能够更好地控制可访问性。 (每种路由和资源的类型及其规则。如果要使用通配符路由(让我称呼它),则需要有条件的块(否则,处理所有不同的情况。这是不必要的操作[直接进行右边的方框中,将路由分开是更好的选择,此外,它还可以使您更好地组织权限处理]。

Route::get('/storage/gallery/{file}', 'System\FileController@getGalleryImage')
->name('storage.gallery.image');

我们现在已经设置了一个或多个控制器

通配符一个

  <?php
     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.  
            }

每条路线一条

(差异很大,是参数,现在它仅引用文件名,而不引用存储磁盘根目录的相对路径)

<?php
public function getCompaniesLogo($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

    $filePath =  config('fs.gallery').DIRECTORY_SEPARATOR.$file; // here in place of just using 'gallery', i'm setting it in a config file

    // here i'm getting only the path from the root  (this way we can change the root later) / also we can change the structor on the store itself, change in one place config.fs.

    // $filePath = Storage::url($file); <== this doesn't work don't use

     // check for existance
    if (!Storage::disk('local')->exists($file)){ // as mentionned precise relatively to storage disk root (this one work well not like Storage:url()
          abort('404');
    } 

    // 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.($file))); // the response()->file() will add the necessary headers in our place
}

现在,您可以通过形成正确的URL进行检查(转到存储文件名之后的副本,并形成路由。它应该向您显示图像)

剩下的最后一件事:

如何在视图中显示

通配符一个

<img src="{{route('routeName', ['fileParam' => $storageRelativePath])}}" />

请注意,以上示例中的routeName将是storage.file,而fileParam将是filePath。例如, $ storageRelativePath 是从数据库中获得的(通常就是这样)。

每条路线

<img src="{{route('routeName', ['fileName' => basename($storageRelativePath)])}}" />

相同,但我们仅提供文件名。

注释: 发送此类回复的最佳方法是使用 response()-> file(); 。 那将在5.7文档中找到。 对于 Image :: make($ storagePath)-> response(); ,该性能明智。除非您需要即时对其进行修改。

您可以使用以下媒体查看我的文章:https://medium.com/@allalmohamedlamine/how-to-serve-images-and-files-privatly-in-laravel-5-7-a4b469f0f706