在 Laravel 中使用 S3
发布于 作者: Chris Fidao
AWS S3 为我们提供了一个存储服务器以外的文件的地方。这样做有一些好处
- 备份/冗余 - S3 及类似服务具有内置备份和冗余功能
- 扩展 - 在现代主机环境(如无服务器或容器化环境)以及传统负载均衡环境中,将文件存储在服务器之外变得**必要**
- 磁盘使用率 - 当将文件存储在云端时,你将不需要那么多的磁盘空间
- 功能 - S3(和其他云)具有一些很棒的功能,例如对文件的版本控制支持、用于删除旧文件(或以更便宜的方式存储)的生命周期规则、删除保护等等
现在使用 S3(即使在单服务器设置中)也可以在长远减少麻烦。以下是您需要了解的内容!
配置
有两个地方可以配置 S3 的内容
- 在 Laravel 中 - 通常通过
.env
文件,但也可能在config/filesystem.php
文件中 - 在你的 AWS 帐户中
Laravel 配置
如果你查看 config/filesystem.php
文件,你会看到 s3
已经是选项之一。它被设置为使用 .env
文件中的环境变量!
除非你需要自定义它,否则你可能可以保留它,只需在 .env
文件中设置值即可
# Optionally Set the default filesystem driver to S3FILESYSTEM_DISK=s3# Or if using Laravel < 9FILESYSTEM_DRIVER=s3 # Add items needed for S3-based filesystem to workAWS_ACCESS_KEY_ID=xxxzzzAWS_SECRET_ACCESS_KEY=xxxyyyAWS_DEFAULT_REGION=us-east-2AWS_BUCKET=my-awesome-bucketAWS_USE_PATH_STYLE_ENDPOINT=false
config/filesystem.php
文件包含以下选项
return [ 'disks' => [ // 'local' and 'public' ommitted... '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'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), ], ],];
那里有一些我们在 .env
文件中没有使用的选项。例如,可以设置 AWS_URL
,这对于使用其他具有 S3 兼容 API 的文件存储云(如 CloudFlare 的 R2 或 Digital Ocean 的 Spaces)非常有用。
AWS 配置
在 AWS 中,你需要做两件事
- 在 S3 服务中创建一个存储桶
- 创建一个 IAM 用户以获取密钥/秘密密钥,然后将一个策略附加到该用户,该策略允许访问 S3 API。
就像 AWS 中的任何事情一样,在 S3 中创建存储桶涉及查看大量的配置选项,并想知道你是否需要它们中的任何一个。对于大多数用例,你不需要!
转到 S3 控制台,创建一个存储桶名称(它必须是全局唯一的,而不仅仅是你的 AWS 帐户中的唯一名称),选择你所在的区域,并保留所有默认设置(包括标记为“此存储桶的阻止公共访问设置”的设置)。
是的,其中一些选项是你可能想要使用的,但你可以在以后选择它们。
创建存储桶后,我们需要权限才能对它进行操作。让我们假设我们创建了一个名为“my-awesome-bucket”的存储桶。
我们可以创建一个 IAM 用户,选择“编程访问”,但不附加任何策略或设置任何其他内容。请务必记录秘密访问密钥,因为它们只显示一次。
我创建了一个视频展示了创建存储桶和设置 IAM 权限的过程:https://www.youtube.com/watch?v=FLIp6BLtwjk
访问密钥和秘密访问密钥应该放在你的 .env
文件中。
接下来,点击进入 IAM 用户并添加一个内联策略。使用 JSON 编辑器编辑它,并添加以下内容(直接来自 Flysystem 文档)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1420044805001", "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:GetObjectAcl", "s3:PutObject", "s3:PutObjectAcl", "s3:ReplicateObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::my-awesome-bucket", "arn:aws:s3:::my-awesome-bucket/*" ] } ]}
这使我们能够对新的存储桶执行必要的 S3 API 操作。
Laravel 使用
在 Laravel 中,你可以像这样使用文件存储
# If you set S3 as your default:$contents = Storage::get('path/to/file.ext');Storage::put('path/to/file.ext', 'some-content'); # If you do not have S3 as your default:$contents = Storage::disk('s3')->get('path/to/file.ext');Storage::disk('s3')->put('path/to/file.ext', 'some-content');
文件(在 S3 中)的路径被附加到存储桶名称,因此名为 path/to/file.ext
的文件将存在于 s3://my-awesome-bucket/path/to/file.ext
中。
从技术上讲,目录不存在于 S3 中。在 S3 中,文件被称为“对象”,文件路径+名称是“对象键”。因此,在存储桶
my-awesome-bucket
中,我们刚刚创建了一个名为path/to/file.ext
的对象。
请务必查看 Laravel 文档的存储区域以查找更多有用的使用 Storage 的方法,包括文件流和临时 URL。
定价
S3 相当便宜 - 我们大多数人每月只需花费几美分到几美元。如果你在使用完文件后从 S3 中删除文件,或者设置生命周期规则在一定时间后删除文件,情况尤其如此。
定价主要取决于三个方面。价格因地区和使用情况而异。以下是一个基于给定月份中真实应用的使用情况的示例,该应用用于 Chipper CI(我的用于 Laravel 应用程序的 CI),它在 S3 中存储大量数据
- 存储:每 GB 0.023 美元,约 992 GB ~= 22.82 美元
- API 调用次数:约 700 万次请求 ~= 12 美元
- 带宽使用情况:这非常不精确。此数据传输费用约为 23 美元,但这不包括基于 EC2 的带宽费用。
关于 S3 的有用信息
- 如果你的 AWS 设置在私有网络中拥有服务器,并使用 NAT 网关,请务必创建一个 S3 端点(网关类型)。这在 VPC 服务中的端点部分完成。这允许对 S3 的调用绕过 NAT 网关,从而避免额外的带宽费用。使用它不会额外收费。
- 如果你担心文件被覆盖或删除,请考虑在你的 S3 存储桶中启用 版本控制
- 请考虑在你的 S3 存储桶中启用 智能分层存储以帮助节省你可能不会在文件变老后再次交互的文件的存储成本
- 请注意,删除大型存储桶(大量文件)可能会花费资金!这是因为你必须执行大量 API 调用才能删除文件。