laravel - 关于在文件系统与数据库上存储 Laravel 文件上传的问题,以及如何在需要时存储在数据库而不是文件系统中
问题描述
刚刚开始在 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 与数据库中的 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 File Facade 是如何工作的,所以这很有帮助:
https://laravel.com/api/8.x/Illuminate/Support/Facades/File.html
作为一个测试用例,当我将文件发布到网络路由时,我看到类似 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 并将其存储在数据库表中,如果我想玩的话周围有那个。
我在 docker 容器中在 NGINX 和 PHP 上运行 Laravel,当我使用 docker exec 检查 /tmp 目录时,我只看到一些日志文件和一堆会话 ID,我认为我的 php 信息将 /tmp 上传为空的。
似乎应该有一种非常简单的方法将其存储在数据库中,而不是文件系统中,如果我愿意的话。
我想先尝试 DB 方法,然后从 /tmp 文件夹中的任何位置以及 Laravel 的文件存储中删除上传。如果我对此不满意,我可以使用文件系统。
配置/文件系统.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是我可以base64encoode,或者不,然后作为BLOB存储在数据库中,我也有存储磁盘的url。这就是我一直在寻找的,因为我不能完成编写代码。生成的示例 url 如下所示:
2/aOkWzxR7W4yH1vaCW2fbft9yY5dO0GVpJs2jHWnM.png
配置/文件系统.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 . . ]);
路线/web.php
Route::middleware(['auth:sanctum', 'verified'])->post('Orders/attach_request', [OrdersController::class, 'attachToRequest']);
不过,我确实有一个问题是该存储容器中的文件是否可以通过网络访问?
我的存储文件夹结构如下所示,其中有一个使用 php artisan storage:link 创建的符号链接,基本上是:
ln -s 存储/应用程序/公共公共/存储
drwxrwxrwx@ app
drwxrwxrwx@ debugbar
drwxrwxrwx@ framework
drwxrwxrwx@ logs
drwxr-xr-x orderattachments
drwxr-xr-x@ requestattachements
我认为 requestattachments 等中的文件是不可访问的,除非我使用辅助函数来获取这些文件,我应该根据需要更改权限吗?
推荐阅读
- c++ - 从指向基类成员函数的指针派生类成员函数的指针
- string - 如何减少内存使用,在序列中搜索第 k 个字符?
- python - Print 打印正确的值,但将不同的值附加到列表中
- javascript - 尝试在 React 中更改状态时出现未定义的错误
- maven - Additional-spring-configuration-metadata.json 仅在第二次构建时与 configurationProperties 生成的元数据合并
- typescript - 我正在尝试创建一个仅允许使用打字稿的数字的文本框。见下面的例子
- java - 正则表达式选择锚标记而不是值
- mysql - 我应该选择多少行?
- javascript - Javascript回调的基本示例中的问题
- database - 维护磁盘上的并发哈希表