gsmeira/laravel-attachments

v0.0.5 2023-09-26 22:02 UTC

This package is auto-updated.

Last update: 2024-09-29 23:56:00 UTC


README

image

  • ✅ 无缝集成
  • ✅ 灵活配置
  • ✅ 适用于无服务器环境
  • ✅ 一个JSON列可以存储记录中的所有文件
  • ✅ 将预定义数据追加到文件基础路径
  • ✅ 内置处理和验证预签名url响应
  • ✅ 路径混淆

安装

1 — 此包需要PHP 8.1和至少Laravel 9.52。要获取最新版本,只需使用Composer即可。

composer require gsmeira/laravel-attachments

2 — 安装完成后,如果您不使用自动包发现,那么您需要将GSMeira\LaravelAttachments\AttachmentsServiceProvider服务提供者在您的config/app.php文件中注册。

3 — 发布配置文件。

php artisan vendor:publish --tag=laravel-attachments

在您的应用config文件夹中将创建一个名为attachments.php的文件。

用法

1 — 在您的.env文件上设置文件系统磁盘。

FILESYSTEM_DISK=<disk>

2 — 在您的模型表的模型中添加一个名为attachmentsjson列。如果您使用的是PostgreSQL,也可以使用jsonb列。

$table->json('attachments')->nullable();

3 —HasAttachments特质添加到您的模型。

class MyModel extends Model
{
    use HasAttachments;
}

4 — 创建或更新时传递有效的附件值。

MyModel::create([
    // ...
    'attachments' => [
        'file' => $request->file,
    ],
]);
$myModel->update([
  // ...
  'attachments' => [
    'file' => $request->file,
  ],
]);

文件将存储在attachments列中,如下所示

{
  "file": "Y5EsfRvITY4SEyP3IBwUMurkkpRo69DfEMEIRlp9.jpg"
}

重要:  附件有两个接受值。第一个是文件直接作为UploadedFile值发送到服务器的情况。第二个是使用预签名url,并期望一个包含有效path键的array的情况。我们将在关于预签名url的部分中更详细地讨论第二种类型。

它是如何工作的?

在使用此包时,您需要了解的主要规则是,每当设置attachments属性时,都会在新的值和之前已存储的值(如果存在)之间执行合并操作。因此,即使您存储了多个文件,您也可以对它们执行单独的操作。以下所有示例即使在存储了多个文件的情况下也可以正常工作。

如何更新/创建附件?

选项1 — 要更新附件,只需为要更新的键设置新值。旧文件将从存储磁盘永久删除。

$myModel->update([
  'attachments' => [
    'file' => $request->file,
  ],
]);

选项2 — 第二种方法是使用updateAttachments方法。

$myModel->updateAttachments([
  'file' => $request->file,
]);

如何删除附件?

选项1 — 将要删除的附件设置为null(或任何无效值)。

$myModel->update([
  'attachments' => [
    'file' => null,
  ],
]);

将删除存储磁盘上的file附件,并将键从附件列中删除。

选项2 — 第二种方法是使用deleteAttachment方法。

$myModel->deleteAttachment('file');

如果您要删除多个文件,可以向此方法提供一个数组。

$myModel->deleteAttachment(['file', 'cover_image']);

如何删除所有附件?

选项1 — 要删除所有文件,可以将附件设置为null

$myModel->update([
  'attachments' => null,
]);

选项2 — 您还可以使用deleteAttachments方法。

$myModel->delateAttachments();

删除模型记录

每次删除具有 HasAttachments 特性的模型记录时,附件列中的所有文件将从存储磁盘上删除。如果你的模型中存在 SoftDeletes 特性,则只有在 forceDelete 时才会删除文件。

全局配置

位于 config/attachments.php 文件中。

文件

file.base_folder

所有附件都将存储的文件夹。 默认: ''

file.appends

将数据库中存储的路径字符串转换为包含额外信息的数组。如果为空,则不会附加到路径。 默认: [ AttachmentsAppend::Path, AttachmentsAppend::Url, AttachmentsAppend::Exists ]

路径

path_obfuscation.enabled

确定路径混淆是否激活。 默认: false

path_obfuscation.levels

定义路径的深度。 默认: 3

签名存储

signed_storage.enabled

如果为 true,则将注册生成预签名URL的路由。 默认: false

signed_storage.temp_folder

使用预签名URL时存储文件的临时文件夹。 默认: tmp

signed_storage.expire_after

预签名URL的过期时间(分钟)。 默认: 5

signed_storage.route

预签名URL的路由配置。

模型配置

如果你想进行更细粒度的配置,可以直接在模型文件中自定义一些选项。

public function attachmentsBaseFolder(): string
{
    return 'users';
}
public function isAttachmentsPathObfuscationEnabled(): bool
{
    return true;
}
public function attachmentsPathObfuscationLevels(): int
{
    return 2;
}
public function attachmentsDisk(): string
{
    return 'private';
}

预签名URL

当使用预签名URL时,你的文件将存储在s3等服务中,文件不再通过服务器发送。相反,应直接从前端上传到云服务,并将此文件的引用发送到服务器。此包期望一个包含应与存储服务中文件位置匹配的 path 的数组。

如何使用这种方法?

1 — 在Laravel应用程序中配置s3 并记得将文件系统磁盘设置为 s3

FILESYSTEM_DISK=s3

2 — 为你的存储桶设置CORS策略,以便向其发送文件。

[
  {
    "AllowedHeaders": [
      "*"
    ],
    "AllowedMethods": [
      "GET",
      "PUT"
    ],
    "AllowedOrigins": [
      "*"
    ],
    "ExposeHeaders": []
  }
]

重要:请注意,在生产环境中,你可能需要比上面的示例更严格的限制。

3 —attachments.php 配置文件中启用和配置预签名URL端点。

4 — 创建一个端点以接收预签名URL响应中的文件。示例

protected function update(User $user, Request $request) {
    $request->validate([
        'file' => ['required', new PreSignedAttachmentRule],
    ]);

    $user->update([
        // ...
        'attachments' => [
            'file' => $request->file,
        ],
    ]);

    // ...
}

始终使用 PreSignedAttachmentRule 检查签名文件是否有效。此规则将检查值是否是包含 path 键的数组,并检查路径是否存在于 s3 上。

5 — 在你的前端,你应该有类似以下的内容。

<input id="file" type="file" />
import axios from 'axios'

axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'

const host = 'https:///'

async function generatePreSignedUrlAndStore(file) {
  const response = await axios.post(`${host}/attachments/signed-storage-url`)

  const headers = response.data.headers

  if ('Host' in headers)
    delete headers.Host

  await axios.put(response.data.url, file, { headers })

  response.data.extension = file.name.split('.').pop()

  return response.data
}

document.querySelector('#file').addEventListener('change', (evt) => {
  const file = evt.target.files[0]

  generatePreSignedUrlAndStore(file).then((response) => {
    axios.post(`${host}/profile-image`, {
      file: {
        path: response.path,
        name: file.name,
        content_type: file.type,
      },
    })
  })
})

测试

在1.0版本发布之前,此包将被完全测试。

许可证

Laravel Attachments 在 MIT 许可证(MIT) 下授权。