关于在文件系统和数据库上存储 Laravel 文件上传的问题,以及如果需要如何在数据库而不是文件系统中存储

Question about Storing Laravel File Uploads on File System vs. Database, and how to Store in DB instead of File System if desired

刚开始在 Laravel 8.x 中使用文件上传。我有一个 UI 构建和路由以及一个控制器,我正在就在哪里以及如何存储文件进行内部辩论。期望文件将是 .gif、.jpg、.png、.pdf、?.docx,可能还有一些视频文件类型,但主要是 .pdf,我们可能会限制为 .pdf 只是为了在开始时更容易。此外,每个文件的文件大小可能不会超过 1-2 MB,并且可能会上限为 10 MB。为此,使用文件系统与数据库有利也有弊。无论如何我都想要一个数据库,所以问题是是只将文件系统的路径存储在数据库中,还是将 mime_type 和其他一些信息连同 BLOB 或 base64 编码版本一起存储在数据库中文件的名称,可能是 base64 版本。

我喜欢使用 BLOB 或 base64 的想法,因为它们在数据库中都是独立的。实际上,查询实际上是相同的,因为您将拥有原始数据或数据库中文件数据的路径。使用 base64 会影响大小,但对于较小的文件大小,不是很大,而且这些文件更容易处理,因为我想使用数据 url 在前端显示文件,或者以其他方式将 blob 转换为 dataurl js。所以,不太确定 BLOB 与 DB 中的 base64 有什么区别。

这只是背景,但欢迎反馈。

我在控制器中遇到的问题可能很简单,因为我从未使用过 Laravel 文件方法。到目前为止我所拥有的就是这个,尽管我可能想将其扩展到一组文件而不是一个文件。

protected function attachToRequest(Request $request) {

    Log::info($request->input('parent'));
    Log::info($request->file('file'));
    Log::info($request->file('file')->getClientOriginalName());
    Log::info($request->file('file')->getMimeType());
    Log::info($request->file('file')->getRealPath());
    Log::info($request->file('file')->getSize());
    Log::info(var_dump($request->file('file')->get()));       
    
}

因为我只是想了解 Laravel 文件门面是如何工作的,所以这很有帮助:

https://laravel.com/api/8.x/Illuminate/Support/Facades/File.html

作为测试用例,当我 post 一个文件到网络路由时,我看到 laravel.log 文件是这样的:

2021-08-07 16:17:16] local.INFO: 2  
[2021-08-07 16:17:16] local.INFO: /tmp/php3pLWBc  
[2021-08-07 16:17:16] local.INFO: x.pdf  
[2021-08-07 16:17:16] local.INFO: application/pdf  
[2021-08-07 16:17:16] local.INFO: /tmp/php3pLWBc  
[2021-08-07 16:17:16] local.INFO: 27856  
[2021-08-07 16:17:16] local.INFO:   

我坚持的部分是如何使用 file_get_contents 或 Facade 方法获取文件的原始数据,以便我可以将其转换为 base64 或只是 BLOB 并存储它在数据库中 table 如果我想玩这个。

我在 NGINX 上有 Laravel 运行,在 docker 容器中有 PHP,当我使用 docker exec 检查 /tmp 目录时,我似乎只是一些日志文件和一堆会话 ID,我认为我的 php 信息将 /tmp 上传列为空。

如果我愿意,似乎应该有一种非常简单的方法将其存储在数据库而不是文件系统中。

我想先尝试 DB 方法,然后从 /tmp 文件夹中的任何位置以及 Laravel 的文件存储中删除上传。如果我对此不满意,我可以使用文件系统。

config/filesystems.php

'disks' => [

    'local' => [
        'driver' => 'local',
        'root' => storage_path('app'),
    ],

    'public' => [
        'driver' => 'local',
        'root' => storage_path('app/public'),
        'url' => env('APP_URL').'/storage',
        'visibility' => 'public',
    ],

    's3' => [
        'driver' => 's3',
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'region' => env('AWS_DEFAULT_REGION'),
        'bucket' => env('AWS_BUCKET'),
        'url' => env('AWS_URL'),
        'endpoint' => env('AWS_ENDPOINT'),
    ],
    'patients' => [
    
        'driver' => 'local',
        'root' => storage_path('patients'),
        'visibility' => 'public',
    ]

],

'links' => [
    public_path('storage') => storage_path('app/public'),
],

如果我要使用文件系统,我可能想为这些文件创建另一个存储路径,例如:

    'request_attachements' => [
    
        'driver' => 'local',
        'root' => storage_path('request_attachements'),
        'visibility' => 'public',
    ]

这似乎回答了我问题的第一部分,对于熟悉使用 Laravel 上传文件的人来说可能是显而易见的。

这似乎行得通,因为我创建了“磁盘”,并在该目录中上传了带有 uuid 和附加文件扩展名的文件。然后我可以使用下面的内容。 $contents是我可以base64编码的,也可以不编码,然后以BLOB的形式存储在数据库中,我也有url到存储盘。这就是我一直在寻找的,因为我无法完成代码的编写。 url 生成的示例看起来像:

2/aOkWzxR7W4yH1vaCW2fbft9yY5dO0GVpJs2jHWnM.png

config/filesystems.php

'requestattachements' => [
        
    'driver' => 'local',
    'root' => storage_path('./requestattachements'),
    'visibility' => 'public',
]

app/Http/Controllers/MyControllers/OrdersController.php

protected function attachToRequest(Request $request) {

    Log::info($request->input('parent'));
    Log::info($request->file('file'));
    Log::info($request->file('file')->getClientOriginalName());
    Log::info($request->file('file')->getMimeType());
    Log::info($request->file('file')->getRealPath());
    Log::info($request->file('file')->getSize());
    
    Storage::makeDirectory('requestattachements');
    $path = $request->file('file')->store(
        $request->input('parent'), 'requestattachements'
    );
    Log::info($path);
    
    $contents = Storage::disk('requestattachements')->get($path);
    Log::info($contents);
    
 }

可选择插入数据库: DB::connection('mysql2')->table('request_attachments')->insert([** Insert stuff here . . ]);

routes/web.php

Route::middleware(['auth:sanctum', 'verified'])->post('Orders/attach_request', [OrdersController::class, 'attachToRequest']);

我确实有一个问题是该存储容器中的文件是否可以通过网络访问?

我的存储文件夹结构如下,还有一个用 php artisan storage:link 创建的符号链接,基本上是:

ln -s storage/app/public public/storage

drwxrwxrwx@  app
drwxrwxrwx@  debugbar
drwxrwxrwx@  framework
drwxrwxrwx@  logs
drwxr-xr-x   orderattachments
drwxr-xr-x@  requestattachements

我认为 requestattachments 等中的文件无法访问,除非我使用辅助函数来获取这些文件,我应该根据需要更改权限?