nestednet / laravel-attachments
Laravel 包,用于将文件附件链接到模型
Requires
- php: >=7.2
- bnbwebexpertise/php-uuid: >=0.0.2
- doctrine/dbal: ~2.5
- illuminate/console: ^6.0
- illuminate/database: ^6.0
- illuminate/encryption: ^6.0
- illuminate/routing: ^6.0
- illuminate/support: ^6.0
- nesbot/carbon: ^2.0
Requires (Dev)
- laravel/framework: ^6.0
README
此包允许快速将文件链接到模型。
也可以安装于 Laravel 5.4,见下文
安装
您可以通过 composer 安装此包。Laravel 5.5+ 自动发现服务提供者。
composer require bnbwebexpertise/laravel-attachments
Laravel 5.4 的旧版安装
为 5.4 支持,请安装版本 0.0.16
composer require bnbwebexpertise/laravel-attachments:0.0.16
然后将服务提供者添加到您的配置中
'providers' => [ // ... Bnb\Laravel\Attachments\AttachmentsServiceProvider::class, // ... ],
配置
您可以通过发布配置文件来自定义此包的行为
php artisan vendor:publish --provider='Bnb\Laravel\Attachments\AttachmentsServiceProvider'
将附件添加到模型类中
将 HasAttachment 特性添加到您的模型类中
<?php namespace App; use Bnb\Laravel\Attachments\HasAttachment; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable, HasAttachment; // ... }
然后使用它将一个文件绑定到一个实例上
$user = App\User::create([ 'name' => 'name', 'email' => 'email@foo.bar', 'password' => 'password', ]); // Bind a local file $attachment = $user->attach('local/path/to/file.txt'); // Bind an uploaded file $attachment = $user->attach(\Request::file('uploaded_file')); // Bind an uploaded file with options $attachment = $user->attach(\Request::file('uploaded_file'), [ 'disk' => 's3', 'title' => \Request::input('attachment_title'), 'description' => \Request::input('attachment_description'), 'key' => \Request::input('attachment_key'), ]);
检索模型的附件
$user = App\User::first(); $allAttachments = $user->attachments()->get(); $attachmentByKey = $user->attachment('myKey'); // Attachment public URL $publicUrl = $attachmentByKey->url;
重新分组模型的附件
group 属性允许对附件进行分组。由 HasAttachment 特性提供的 attachmentsGroup 方法返回所有具有给定 group 值的附件。
$user = App\User::first(); $user->attach($somefile, [' 'group' => 'album', ']); $user->attach($otherfile, [' 'group' => 'album', ']); $attachmentsByGroup = $user->attachmentsGroup('album');
删除附件
在附件模型实例上调用 delete() 方法将删除数据库行和文件。可以通过将配置中的 behaviors.cascade_delete 设置为 false 来禁用文件的删除。
注意,在类似
query()的查询上调用delete()将不会级联到文件系统,因为它不会调用Attachment模型类的delete()方法。
$user = App\User::first(); $attachmentByKey = $user->attachment('myKey'); $attachmentByKey->delete(); // Will also delete the file on the storage by default
挂钩文件输出
Bnb\Laravel\Attachments\Attachment 模型类提供了一个 outputting 事件,您可以观察它。
在应用服务提供者中,您可以写入如下代码
<?php use Bnb\Laravel\Attachments\Attachment; class AppServiceProvider extends ServiceProvider { // ... public function boot() { // ... Attachment::outputting(function ($attachment) { /** @var Attachment $attachment */ // Get the related model $model = $attachment->model; if (empty($model)) { // Deny output for attachments not linked to a model return false; } if ($model instanceof \App\User) { // Check if current user is granted and owner $user = \Auth::user(); return $user && $user->can('download-file') && $user->id == $model->id; } }); // ... } // ... }
Dropzone
上传
此包提供了通过 attachments.dropzone 路由别名对 Dropzone.js 或等效服务的服务器端点。
它以 JSON 响应返回附件 uuid 和其他字段。此值可以稍后发送回服务器以将其绑定到模型实例(延迟保存)。
表单
<form action="{{ route('attachments.dropzone') }}" class="dropzone" id="my-dropzone"> {{ csrf_field() }} </form>
响应
{
"title": "b39ffd84524b",
"filename": "readme.md",
"filesize": 2906,
"filetype": "text\/html",
"uuid": "f5a8eec2-d860-4e53-8451-b39ffd84524b",
"key": "58ac52e90db938.72105394",
"url": "http:\/\/laravel.dev:8888\/attachments\/f5a8eec2-d860-4e53-8451-b39ffd84524b\/readme.md"
}
稍后发送回
<form action="/upload" method="post"> {{ csrf_field() }} <input type="hidden" name="attachment_id" id="attachment_id"> <button type="submit">Save</button> </form> <!-- Where attachment_id is populated on success --> <script> Dropzone.options.myDropzone = { init: function () { this.on("success", function (file, response) { document.getElementById('attachment_id').value = response.uuid; }); } }; </script>
稍后绑定值
<?php Route::post('/upload', function () { $model = App\User::first(); Bnb\Laravel\Attachments\Attachment::attach(Request::input('attachment_id'), $model); return redirect('/dropzone'); });
删除
可以通过 HTTP DELETE 调用 attachments.dropzone.delete 路由。必须提供附件 ID 作为参数。
此路由提供的删除操作 仅适用于待处理附件(未绑定到模型)。
为防止删除其他用户的文件,当前 CSRF 令牌在通过 dropzone 端点上传时保存,并且在调用 dropzone 删除端点时必须相同。此行为可以通过配置或环境键(见 config/attachments.php)禁用。
使用示例
<script> var MyDropzone = { url: "{{ route('attachments.dropzone.delete', ['id' => ':id']) }}" // ... deletedfile: function (file) { axios.delete(this.url.replace(/:id/, file.id)).then(function () { //... }); } //... } </script>
事件
dropzone 端点控制器会触发两个事件
attachments.dropzone.uploading,参数为$request : Requestattachments.dropzone.deleting,参数为$request : Request和$file : Attachement
如果任何监听器返回 false,则操作将被中止。
public function boot() { Event::listen('attachments.dropzone.uploading', function ($request) { return $this->isAllowedToUploadFile($request); }); Event::listen('attachments.dropzone.deleting', function ($request, $file) { return $this->canDeletePendingFile($request, $file); }); }
临时 URL
可以通过Attachment模型的getTemporaryUrl方法生成一个唯一的临时URL来下载附件,主要用于分享。getTemporaryUrl方法有一个参数:一个Carbon日期,在此日期后链接将不再有效。
默认生成的URL形式为:http://example.com/attachments/shared/<一个非常长的字符串>。分享路径可以在配置文件中的shared_pattern键下进行修改。
清理命令
提供了一个命令来清理与模型未绑定的附件(当model_type和model_id为null时)。
php artisan attachment:cleanup
可以使用-s(或--since=[timeInMinutes])选项来指定另一个时间限制(以分钟为单位):只有比指定年龄更早的无绑定文件将被删除。此值默认设置为1440。
自定义
为模型设置自定义数据库连接名称
您可以通过以下方式自定义数据库连接名称:
- 添加一个用于
ATTACHMENTS_DATABASE_CONNECTION的.env变量(推荐)或者 - 更改
config/attachments.php中的配置选项attachments.database.connection。
扩展附件模型列
配置定义了在attachment.attributes键中的可填充附件属性列表。
这允许您创建迁移来在附件表中添加新列,并在config/attachments.php的发布配置中声明它们。
自定义附件存储目录前缀
您可以通过以下方式轻松自定义存储新附件的文件夹/前缀:
- 添加一个用于
ATTACHMENTS_STORAGE_DIRECTORY_PREFIX的.env变量(推荐)或者 - 更改
config/attachments.php中的配置选项attachments.storage_directory.prefix。
默认值为attachments,任何尾随的/将被自动删除。
自定义附件存储文件路径
如果您不想使用默认的存储文件路径生成方式,可以提供filepath选项(相对于存储磁盘的根目录)。它必须包含目录和文件名。确保提供的文件路径不与另一个文件冲突的责任在于您。
$model->attach('/foo/bar/pdf.pdf', ['filepath' => 'foo/bar/test.pdf']);
此选项不适用于通过集成DropZone控制器上传的附件。仅适用于显式附件。
扩展附件模型类
这有助于向附件模型添加一些关系。
创建一个扩展Bnb\Laravel\Attachments\Attachment的自己的模型
<?php namespace Foo\Models; MyAttachment extends Bnb\Laravel\Attachments\Attachment { public function someCustomRelation() { // } }
在服务提供者中将您的模型绑定到Bnb\Laravel\Attachments\Contracts\AttachmentContract接口
public function register() { // ... $this->app->bind( \Bnb\Laravel\Attachments\Contracts\AttachmentContract::class, \Foo\Models\MyAttachment::class ); // ... }