表单构造器 - 字段
文件上传
概述
文件上传(FileUpload)字段是基于 Filepond 的。
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment')
Filament 也支持
spatie/laravel-medialibrary
。更多详情请查阅插件文档。
配置存储磁盘和存储目录
默认情况下,文件会公开上传到配置文件中定义的存储盘。你也可以设置 FILAMENT_FILESYSTEM_DISK
环境变量对此进行修改。
要正确预览图片及其他文件,FilePond 要求将文本保存到与应用相同的域名中,或者设置合适的 CORS 头。请确保
APP_URL
环境变量设置正确;或者修改文件系统(filesystem)驱动,设置成正确的 URL。如果文件托管到另外的域名,比如 S3,请确保设置了 CORS 头部。
要为特定字段修改磁盘和目录以及文件的可见度,请使用 disk()
、directory()
及 visibility()
方法:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->disk('s3') ->directory('form-attachments') ->visibility('private')
是否从磁盘中删除这些文件由开发者决定,因为 Filament 无从知晓这些图片是否有其他地方的依赖。其中一种自动实现方式是监测模型事件。
多文件上传
你也可以上传多个文件。URL 以 JSON 格式存储:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple()
如果你使用 Eloquent 来保存文件 URL,请确保将 array
cast 添加到对应的模型属性中:
use Illuminate\Database\Eloquent\Model; class Message extends Model{ protected $casts = [ 'attachments' => 'array', ]; // ...}
控制文件名
默认情况下,新上传的文件会生成随机文件名。这是为了确保不会和现有的文件产生冲突。
控制文件名的安全提示
在使用 preserveFilenames()
或 getUploadedFileNameForStorageUsing()
方法之前,请注意安全隐患。如果允许用户使用自己的文件名上传文件,则有一些方法可以利用这些方法上传恶意文件,即使使用 acceptedFileTypes()
方法来限制可以上传的文件类型,这也适用,因为它使用 Laravel 的 mimetypes
规则,该规则不验证文件的扩展名,只验证其 mime 类型,该类型可以被操纵。
这对于在 TemporaryUploadedFile
对象上使用 getClientOriginalName()
方法(这也是 preserveFilenames()
方法所使用的),特别是一个问题。默认情况下,Livewire 为上传的每个文件生成一个随机文件名,并使用文件的 mime 类型来确定文件扩展名。
如果攻击者上传了一个具有欺骗性 mime 类型的 PHP 文件,则将这些方法与 local
或 public
文件系统磁盘一起使用将使你的应用容易受到远程代码执行攻击使用 S3 磁盘可以保护你免受这种特定的攻击向量的攻击,因为 S3 不会像服务器从本地存储提供文件时那样执行 PHP 文件。
如果你使用的是 local
或 public
磁盘,则应考虑使用 storeFileNamesIn()
方法将原始文件名存储在数据库的单独列中,并将随机生成的文件名保留在文件系统中。这样,你仍然可以向用户显示原始文件名,同时确保文件系统的安全。
除了这个安全问题之外,你还应该意识到,允许用户使用自己的文件名上传文件可能会导致与现有文件发生冲突,并使管理存储变得困难。如果不将文件限定到特定目录,用户可能会上传同名文件,并覆盖其他文件的内容,因此在任何情况下,这些功能都只能由受信任的用户访问。
保留原始文件名
重要:使用该特性时,请确保阅读对应的安全提示。
使用 preserveFilenames()
方法,可以保留上传文件的原始文件名:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->preserveFilenames()
生成自定义文件名
重要:使用该特性时,请确保阅读对应的安全提示。
使用 getUploadedFileNameForStorageUsing()
方法,你可以完全自定义文件名的生成方式,并基于上传的文件 $file
在闭包中返回字符串:
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile; FileUpload::make('attachment') ->getUploadedFileNameForStorageUsing( fn (TemporaryUploadedFile $file): string => (string) str($file->getClientOriginalName()) ->prepend('custom-prefix-'), )
将原始文件名单独存储
使用 storeFileNamesIn()
方法,你可以保留随机生成的文件名的同时,将原始文件名存储起来:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->storeFileNamesIn('attachment_file_names')
attachment_file_names
现在将会存储上传文件的原始文件名,在表单提交后将其存入到数据库中。如果通过 multiple()
实现多文件上传,请确保将 array
cast 添加到该 Eloquent 模型属性中。
头像模式
使用 avatar()
方法,你可以为上传文件启用头像模式:
use Filament\Forms\Components\FileUpload; FileUpload::make('avatar') ->avatar()
这只允许上传图片,并且在上传后它将会在一个紧凑的圆中展示图片,这很适合于头像。
该特性与圆形裁切是绝佳匹配。
图片编辑器
你可以使用 imageEditor()
方法,为文件上传字段启用图片编辑器:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageEditor()
当你通过点击铅笔图标上传图片时,你可以打开该编辑器。你也可以在现有图片上点击铅笔图标打开图片编辑器,这将在保存时删除并重新上传图片。
允许用户按长宽比裁切图片
使用 imageEditorAspectRatios()
方法,你可以允许用户按照一套指定的长宽比裁切图片:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageEditor() ->imageEditorAspectRatios([ '16:9', '4:3', '1:1', ])
传入 null
作为选项,你也可以允许用户不选择长宽比:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageEditor() ->imageEditorAspectRatios([ null, '16:9', '4:3', '1:1', ])
设置图片编辑器模式
使用 imageEditorMode()
方法,你可以修改图片编辑器模式,该方法可接收 1
、2
或 3
作为参数。这些选项的解释可以在 Cropper.js 文档中查看:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageEditor() ->imageEditorMode(2)
自定义图片编辑器的空填充色
默认情况下,图片编辑器会使图片周围的空白区域透明。使用 imageEditorEmptyFillColor()
方法可以自定义空白区域的填充色:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageEditor() ->imageEditorEmptyFillColor('#000000')
设置图片编辑器的视窗大小
使用 imageEditorViewportWidth()
和 imageEditorViewportHeight()
方法可以修改图片编辑器的视窗,在跨设备中使用会生成长宽比:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageEditor() ->imageEditorViewportWidth('1920') ->imageEditorViewportHeight('1080')
允许用户将图片裁切成圆
使用 circleCropper()
方法,可以允许用户将图片裁切成圆:
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->avatar() ->imageEditor() ->circleCropper()
这与 avatar()
方法完美结合,其以紧凑的圆形布局渲染图像。
不使用编辑器裁切和调整图标大小
Filepond 允许你在上传之前,在不需要单独编辑器的情况下,裁切图片及调整图片大小。你可以使用 imageCropAspectRatio()
、imageResizeTargetHeight()
和 imageResizeTargetWidth()
方法自定义这些行为。应该为这三个方法设置 imageResizeMode()
使之生效, 可设置成 force
、cover
或 contain
三者其中之一。
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image() ->imageResizeMode('cover') ->imageCropAspectRatio('16:9') ->imageResizeTargetWidth('1920') ->imageResizeTargetHeight('1080')
修改文件上传区域的外观
你也可以修改 Filepond 组件的通用外观。这些方法的可用选项可以在 Filepond 网站中查看。
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->imagePreviewHeight('250') ->loadingIndicatorPosition('left') ->panelAspectRatio('2:1') ->panelLayout('integrated') ->removeUploadedFileButtonPosition('right') ->uploadButtonPosition('left') ->uploadProgressIndicatorPosition('left')
在 Grid 中禁用文件
通过设置 panelLayout()
,使用 Filepond grid
布局:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->panelLayout('grid')
文件重新排序
使用 reorderable()
方法,你可以允许用户对上传文件重新排序:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->reorderable()
使用该方法时,FilePond 可能将新上传的文件放到列表前面,而不是尾部。要对此进行修改,请使用 appendFiles()
方法:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->reorderable() ->appendFiles()
在新标签页中打开文件
使用 openable()
方法,你可以添加一个按钮,用来在新标签页中打开每个文件:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->openable()
下载文件
使用 downloadable()
方法,你可以为每个文件添加一个下载按钮:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->downloadable()
预览文件
默认情况下,有些文件类型可以在 FilePond 中预览中。如果你想禁用所有文件的预览,你可以使用 previewable(false)
方法:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->previewable(false)
表单提交时移动文件而不是复制文件
默认情况下,文件最初上传到 Livewire 的临时存储目录,然后在表单提交后将其复制到目标目录。如果你希望移动文件,加入上传的临时文件和永久文件存储在同一个磁盘上,你可以使用 moveFiles()
方法:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->moveFiles()
防止文件被永久存储
如果你想在表单提交时,阻止文件被永久存储,你可以使用 storeFiles(false)
方法:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->storeFiles(false)
表单提交后,会返回临时文件上传对象,而不是持久化的文件存储路径。这非常适合像导入的 CSV 这样的临时文件。
请注意,图片、视频和音频文件不会再表单预览中展示存储的文件名,除非你使用了 previewable(false)
。这是因为 FilePond 预览插件的限制。
根据 EXIF 数据确定图像的方向
默认情况下,FilePond 会根据 EXIF 数据自动确定图片方向。使用 orientImagesFromExif(false)
方法,你可以禁用该行为:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->orientImagesFromExif(false)
隐藏移除文件按钮
使用 deletable(false)
,可以隐藏移除已上传的文件按钮:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->deletable(false)
阻止文件信息获取
表单加载后,会自动检测文件是否存在、文件大小和文件类型。这些都在后台实现。当使用具有许多文件的远程存储时,这一操作可能会消耗许多时间,你可以使用 fetchFileInformation(false)
方法禁用该特性:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->fetchFileInformation(false)
自定义上传消息
使用 uploadingMessage()
方法,你可以自定义显示在表单提交按钮中的上传消息:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->uploadingMessage('Uploading attachment...')
文件上传验证
除了验证页面中列出的所有规则之外,还有一些其他专用于文件上传的验证规则。
由于 Filament 是由 Livewire 驱动并使用其文件系统,因此你也需要参考 config/livewire.php
文件中的默认文件上传验证规则。这也控制了最大 12MB 的文件大小。
文件类型验证
使用 acceptedFileTypes()
,并在其中传入一个 MIME 类型数组,你可以限制上传的文件类型:
use Filament\Forms\Components\FileUpload; FileUpload::make('document') ->acceptedFileTypes(['application/pdf'])
你也可以使用 image()
作为简写,以允许所有图片 MIME 类型。
use Filament\Forms\Components\FileUpload; FileUpload::make('image') ->image()
文件大小验证
你也可以限制上传文件的大小,以 KB 计:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachment') ->minSize(512) ->maxSize(1024)
上传大文件
如果你在上传大文件时遇到问题,例如 HTTP 请求失败,浏览器控制台中的响应状态为 422,你可能需要调整配置。
在服务器的 php.ini
文件中,提高最大文件大小可能可以解决问题:
post_max_size = 120Mupload_max_filesize = 120M
Livewire 也会在验证前验证文件大小。要发布 Livewire 配置文件,请运行
php artisan livewire:publish --config
可以在 temporary_file_upload
的 rules
键中调整最大上传大小。下例规则中使用了 KB,120 MB 为 122880 KB:
'temporary_file_upload' => [ // ... 'rules' => ['required', 'file', 'max:122880'], // ...],
文件数量验证
使用 minFiles()
和 maxFiles()
方法,你可以自定义可以上传的文件数量:
use Filament\Forms\Components\FileUpload; FileUpload::make('attachments') ->multiple() ->minFiles(2) ->maxFiles(5)
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion