ahmedkandel/nova-s3-multipart-upload

一个 Laravel Nova S3 分片上传工具。

v2.0.0 2024-02-08 12:04 UTC

This package is auto-updated.

Last update: 2024-09-08 13:37:54 UTC


README

Latest Version on Packagist Total Downloads License

一个 Laravel Nova 资源工具,可以直接上传文件到 Amazon S3。您可以上传、下载或删除单个、多个、小或大文件。

screenshot

⚡ 功能

  • 安全:不会将敏感数据(包括 AWS 凭据)暴露给前端。上传和下载的文件将永远不会通过您的服务器,以提供额外的保护和性能。

  • 灵活:文件信息可以存储在模型属性中,或作为单个模型属性下的数组,甚至作为关系。

  • 稳健:基于优秀的组件,Uppy 文件上传器,Laravel Nova 控制台和 Amazon S3 存储。

  • 可定制:使用链式 方法 提供广泛的定制选项。

  • 图片编辑器、自定义元字段、分片上传、摄像头录制、屏幕捕获、授权、本地化、...

📌 安装

composer require "ahmedkandel/nova-s3-multipart-upload"

💡 使用方法

在您的 Nova 资源类中将 NovaS3MultipartUpload 工具添加到字段中

use Ahmedkandel\NovaS3MultipartUpload\NovaS3MultipartUpload;

class Post extends Resource
{
    public function fields(Request $request)
    {
        return [
            // ...
            NovaS3MultipartUpload::make('Video'),
        ];
    }
}

注意: make 方法需要一个“可读”的名称,它将尝试猜测属性名称。您可以将属性名称作为第二个参数传递。

注意:属性名称用于存储文件路径或文件信息(在 storeAsArray/storeAsMultipleArray 的情况下)或关系模型(在 hasOne/hasMany 的情况下)。

注意: hasOne/hasMany 方法对 morphOne/morphMany 也有效。

在您的模型类中添加所有要填充的属性到 $fillable

class Post extends Model
{
    protected $fillable = ['video'];
}

当使用 storeAsArraystoreAsMultipleArray 方法时,您需要在模型类中将属性转换为数组

class Post extends Model
{
    protected $casts = [
        'videos' => 'array',
    ];
}

⚙️ S3 配置

在创建您的 S3 存储桶并将其连接到您的 Laravel 项目后,您需要额外一步来配置 S3 存储桶的“跨域资源共享 (CORS)”为 JSON 或 XML(这不是“存储桶策略”)

JSON

[
    {
        "AllowedOrigins": [
            "http://your-domain.com"
        ],
        "AllowedMethods": [
            "GET",
            "PUT"
        ],
        "AllowedHeaders": [
            "Authorization",
            "x-amz-date",
            "x-amz-content-sha256",
            "content-type"
        ],
        "ExposeHeaders": [
            "ETag"
        ],
        "MaxAgeSeconds": 3000
    },
    {
        "AllowedOrigins": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "MaxAgeSeconds": 3000
    }
]

XML

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>http://your-domain.com</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>Authorization</AllowedHeader>
    <AllowedHeader>x-amz-date</AllowedHeader>
    <AllowedHeader>x-amz-content-sha256</AllowedHeader>
    <AllowedHeader>content-type</AllowedHeader>
    <ExposeHeader>ETag</ExposeHeader>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
  </CORSRule>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
  </CORSRule>
</CORSConfiguration>

注意:请将 http://your-domain.com 替换为您的前端域名。

✂️ 方法

  • 文件存储

    • ->disk($disk) 设置 S3 磁盘名称,默认为 's3'。

    • ->path($path) 设置存储路径,默认为存储桶根目录。

    • ->keepOriginalName() 保留文件原始名称,默认是自动生成哈希名称“这是推荐的做法”。

  • 文件信息

    • ->storeName($fileNameColumn) 将文件名存储在这个属性/列/键中。您可以在上传面板中编辑文件名。

    • ->storeSize($fileSizeColumn) 将文件大小(以字节为单位)存储在这个属性/列/键中。大小将在文件卡片上格式化(以 KB、MB...为单位)。

    • ->storeMeta($array) 存储其他元数据并创建 UI 以从上传面板处理它们。$array 的键是属性/列/键。例如:

       ->storeMeta(
           [
               'file_author' => [
                   'name' => 'Author',
                   'placeholder' => 'your name please!',
                   'default' => 'No Author',
               ],
               'file_description' => [
                   'name' => 'Description',
               ],
               'file_uploaded_at' => [
                   'name' => 'Uploaded At',
                   'default' => now(),
                   'ui' => false,
               ],
           ]
       )
  • 模型属性

    默认情况下,文件路径存储在由 make 方法指定的模型属性中。然后如果添加了其他文件信息(文件名、文件大小、元数据),它们将存储在相应的属性中。

    为了提高灵活性,所有这些属性都可以存储在一个由 make 方法定义的单个模型属性下的关联数组中。

    • ->storeAsArray($fileKeyColumn) 设置将包含文件路径的数组键。

    • ->storeAsMultipleArray($fileKeyColumn)storeAsArray 类似,但允许存储多个文件。

    如果您想将文件信息存储在与由 make 方法定义的“主”模型属性相关的“子”模型中。

    • ->hasOne($fileKeyColumn) 设置将保存文件路径的相关模型属性,也适用于 morphOne

    • ->hasMany($fileKeyColumn)hasOne 类似,但允许存储多个文件,也适用于 morphMany

    • ->refreshListable() 每次上传或删除文件时,刷新资源详情视图中的可列表字段 HasOneHasMany

  • 上传器选项

    • ->autoProceed() 选择第一批文件后自动开始上传。

    • ->allowMultipleUploads() 允许在上传第一批文件后添加更多文件。

    • ->restrictions($array) 限制上传文件类型和/或数量的规则和条件。例如:

       ->restrictions(
           [
               'maxFileSize' => 1024 * 1024 * 1024,
               'minFileSize' => 50 * 1024,
               'maxTotalFileSize' => 10 * 1024 * 1024 * 1024,
               'maxNumberOfFiles' => 10,
               'minNumberOfFiles' => 2,
               'allowedFileTypes' => [
                   'image/*',
                   'video/*',
                   '.pdf',
               ],
           ]
       )
    • ->simultaneousChunks($integer) 允许同时上传的最大块数量。

    • ->chunkSize($integer) 上传文件时使用的最小块大小(字节)。

    • ->panelHeight($integer) 上传器面板的高度(像素)。

    • ->fileManagerSelectionType($string) 通过文件管理器窗口进行选择的类型('files', 'folders', 'both'),默认为 'files'。

    • ->footerNote($string) 显示在上传器面板底部文本。当使用 restrictions 时很有用,用于提供说明。

    • ->displayPoweredByUppy() 在上传器面板上显示 Uppy 团队 信用。

    • ->translate($array) 本地化上传器面板。例如:

       ->translate(
           [
               'dropPasteImportBoth' => 'Trascina i file qui, sfoglia %{browseFiles} o %{browseFolders}',
               'browseFiles' => 'i file',
               'browseFolders' => 'le cartelle',
               'myDevice' => 'Dispositivo',
               'screencast' => 'Schermo',
           ]
       )

      注意 您可以从 这里 获取可用的 $array 键列表。

  • 文件卡片

    • ->contentDisposition($array) 浏览器如何处理文件下载,例如 ['attachment']['inline'] 或两者都是 ['inline', 'attachment'],默认为 ['attachment']

✔️ 示例

上传多个文件及其(名称、大小、元数据)。然后将在 User 模型的 files 属性中保存文件信息作为多个数组。

User 模型类

class User extends Model
{
    protected $fillable = ['files'];
    
    protected $casts = [
        'files' => 'array',
    ];
}

User 资源类

use Ahmedkandel\NovaS3MultipartUpload\NovaS3MultipartUpload;

class User extends Resource
{
    public function fields(Request $request)
    {
        return [
            // ...
            NovaS3MultipartUpload::make('Files')
                ->path($request->user()->id.'-uploads')
                ->storeAsMultipleArray('file_path')
                ->storeName('file_name')
                ->storeSize('file_size')
                ->storeMeta(
                    [
                        'file_author' => [
                            'name' => 'Author',
                            'placeholder' => 'your name please!',
                            'default' => 'No Author',
                        ],
                        'file_description' => [
                            'name' => 'Description',
                        ],
                    ]
                ),
        ];
    }
}

预览

upload

当文件上传时,用户模型的文件属性 \App\User::find(1)->files 将具有以下值:

[
    {
        "file_name": "Video.mkv",
        "file_path": "1-uploads/To5SvZLTyT1XQcUWCTpmqH6GfrgLmoep0tP6EV9n.mkv",
        "file_size": 207683,
        "file_author": "No Author",
        "file_description": null
    },
    {
        "file_name": "Document.pdf",
        "file_path": "1-uploads/RnEBFKa0EqDoKQRkXf27l4dZ7fQ8MTyBofMK202b.pdf",
        "file_size": 77395,
        "file_author": "Ahmed Kandil",
        "file_description": "DDD"
    }
]

🛂 授权

Nova 使用 ->canSee(closure) 方法授权用户查看资源工具,该方法接受一个返回 truefalse 的闭包。

我们为此工具添加了更多方法以进行更细致的控制

  • ->canUpload(closure) 允许用户上传文件并显示上传器面板。

  • ->canView(closure) 允许用户列出已上传的文件并显示文件网格。

  • ->canDownload(closure) 允许用户下载文件并在文件卡片中显示下载按钮。

  • ->canDelete(closure) 允许用户删除文件并在文件卡片中显示删除按钮。

例如,如果您想允许用户上传只有当没有文件属性为空时

->canUpload(function () {
    return empty($this->model()->video);
})

例如,如果您想允许用户删除他自己的模型(帖子或视频)中的文件

->canDelete(function () {
    return request()->user()->id === $this->model()->user_id;
})

注意 默认情况下,所有操作都是授权的,直到您拒绝它们。

🔌 插件

  • 图像编辑器: 使用 ->useImageEditor($array) 方法启用 Uppy Image Editor 插件。该插件使用优秀的 Cropper.js

    选项 该方法接受一个选项数组

     [
     	'autoOpen' => true,
     ]

    注意 编辑器将仅针对图像文件激活。

  • 网络摄像头: 使用 ->useWebcam() 方法启用 Uppy Webcam 插件。然后您可以录制视频并拍照上传。

    注意 要使用摄像头,需要 https 连接。

  • 屏幕录制:使用 ->useScreenCapture() 方法启用 Uppy Screen Capture 插件。然后您可以录制屏幕或应用程序以供上传。

    注意 要使用屏幕录制,需要 https 连接。

⚠️ 备注

此包是资源工具 而不是 资源字段。这意味着它仅作为面板在资源详细视图下可见,不能插入到其他面板或选项卡中,它必须是资源字段数组的直接子元素。

原因是什么? 经过深思熟虑,我们发现将文件上传操作放在创建新模型的同一请求中不是一个好主意。因为响应时长将取决于文件上传进度,这意味着用户必须等待,没有任何可视提示,希望一切都能正常工作。因此,我们决定将文件(上传 | 下载 | 删除)的处理过程与模型(创建 | 编辑)的处理过程分开。

📜 更新日志

有关最近更改的更多信息,请参阅 更新日志

🤝 许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件