0

0

使用PHP SDK高效列出S3桶指定前缀下的顶层对象

碧海醫心

碧海醫心

发布时间:2025-11-22 13:59:20

|

304人浏览过

|

来源于php中文网

原创

使用PHP SDK高效列出S3桶指定前缀下的顶层对象

本文详细介绍了如何在php中使用aws sdk,通过`listobjects`方法结合`prefix`和`delimiter`参数,精准地从amazon s3桶中获取指定路径下的第一层对象(即模拟子目录),而不会递归列出深层文件或子目录。通过实例代码,演示了如何配置请求参数并处理返回结果,以实现对s3对象列表的精细化控制,有效模拟文件系统层级结构。

理解S3的扁平结构与层级模拟

Amazon S3本质上是一个扁平的对象存储服务,它不直接支持传统文件系统中的目录或文件夹概念。所有的"文件"(对象)都存储在一个桶中,并通过唯一的键(Key)来标识。然而,为了方便用户管理和理解,S3允许通过键的命名约定(通常使用斜杠/作为分隔符)来模拟目录结构。

在某些场景下,我们可能需要列出某个特定“目录”下的第一层“子目录”或“文件”,而不希望深入到更深的层级。例如,给定一个路径public/uploads/test_company/,我们只想获取public/uploads/test_company/test1和public/uploads/test_company/test2这样的顶层对象(或模拟的子目录),而忽略public/uploads/test_company/test1/test.txt这类深层文件。

为了实现这一目标,AWS S3的listObjects(或listObjectsV2)API提供了Prefix和Delimiter这两个关键参数。

核心参数详解:Prefix 与 Delimiter

Prefix(前缀)

Prefix参数用于过滤结果,只返回键名以指定字符串开头的所有对象。它相当于在文件系统中进入一个特定目录。

立即学习PHP免费学习笔记(深入)”;

  • 作用: 将列表范围限定在所有键名都以给定前缀开始的对象。
  • 示例: 如果Prefix设置为public/uploads/test_company/,则所有以该字符串开头的对象(包括public/uploads/test_company/test1、public/uploads/test_company/test2、public/uploads/test_company/test1/test.txt等)都将被考虑。

Delimiter(分隔符)

Delimiter参数是实现单层列表的关键。当指定了分隔符时,S3会根据这个分隔符对匹配Prefix的对象键进行分组。

  • 作用:
    1. 它会返回所有在Prefix和第一个Delimiter之间没有其他Delimiter的“直接”对象(这些对象会在响应的Contents部分)。
    2. 更重要的是,它会返回所有在Prefix之后、第一个Delimiter之前存在一个Delimiter的“共同前缀”(CommonPrefixes)。这些共同前缀实际上就是我们所说的“子目录”。
  • 示例: 如果Prefix是public/uploads/test_company/,Delimiter是/:
    • S3会查找所有以public/uploads/test_company/开头,并且在public/uploads/test_company/之后、下一个/之前没有其他/的对象。
    • 对于public/uploads/test_company/test1/test.txt,它的共同前缀是public/uploads/test_company/test1/。
    • 对于public/uploads/test_company/test2,它是一个直接对象(如果test2不是以/结尾的)。但如果test2本身是一个模拟的目录,其内部有文件,那么test2/将作为一个共同前缀返回。

通过同时使用Prefix和Delimiter,我们可以有效地告诉S3:“给我列出在Prefix路径下,以Delimiter作为层级分隔符的第一层所有内容。”

使用PHP SDK实现单层对象列表

下面是使用AWS SDK for PHP 3.x 来获取S3桶中指定前缀下第一层对象的示例代码。

PathFinder
PathFinder

AI驱动的销售漏斗分析工具

下载

准备工作

首先,确保你已经安装了AWS SDK for PHP:

composer require aws/aws-sdk-php

然后,配置你的AWS凭证和区域。

示例代码

<?php

require 'vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\Exception\AwsException;

// 1. 配置S3客户端
// 确保替换为你的AWS凭证和区域
$s3Client = new S3Client([
    'version'     => 'latest',
    'region'      => 'your-aws-region', // 例如 'us-east-1'
    'credentials' => [
        'key'    => 'YOUR_AWS_ACCESS_KEY_ID',
        'secret' => 'YOUR_AWS_SECRET_ACCESS_KEY',
    ],
]);

// 2. 定义桶名和目标前缀
$bucketName = 'your-s3-bucket-name'; // 替换为你的S3桶名
$targetPrefix = 'public/uploads/test_company/'; // 目标路径前缀

try {
    // 3. 调用listObjects方法,并设置Prefix和Delimiter
    $result = $s3Client->listObjects([
        'Bucket'    => $bucketName,
        'Prefix'    => $targetPrefix,
        'Delimiter' => '/', // 使用斜杠作为分隔符,模拟目录层级
    ]);

    echo "Listing top-level objects under: " . $targetPrefix . "\n";

    // 4. 处理返回结果:CommonPrefixes 和 Contents

    // CommonPrefixes 包含模拟的子目录
    if (isset($result['CommonPrefixes'])) {
        echo "\n--- Simulated Subdirectories (CommonPrefixes) ---\n";
        foreach ($result['CommonPrefixes'] as $commonPrefix) {
            // CommonPrefixes会包含完整的路径,且通常以分隔符结尾,例如 "public/uploads/test_company/test1/"
            $folderName = rtrim($commonPrefix['Prefix'], '/'); // 移除末尾的斜杠
            echo "Folder: " . $folderName . "\n";
        }
    } else {
        echo "No simulated subdirectories found.\n";
    }

    // Contents 包含直接在该Prefix下的文件(不包含子目录内的文件)
    if (isset($result['Contents'])) {
        echo "\n--- Direct Files (Contents) ---\n";
        foreach ($result['Contents'] as $object) {
            // 确保这个对象不是Prefix本身(如果Prefix以/结尾,S3可能会将其自身作为一个空对象返回)
            if ($object['Key'] !== $targetPrefix) {
                echo "File: " . $object['Key'] . " (Size: " . $object['Size'] . " bytes)\n";
            }
        }
    } else {
        echo "No direct files found at this level.\n";
    }

} catch (AwsException $e) {
    // 捕获S3操作可能抛出的异常
    echo "Error listing objects: " . $e->getMessage() . "\n";
}

?>

代码解释

  1. S3客户端初始化: 使用你的AWS凭证和区域初始化S3Client。
  2. Bucket和Prefix: 指定你想要操作的S3桶名称和目标路径前缀。
  3. Delimiter: 将Delimiter设置为/。这是关键,它告诉S3将/视为目录分隔符。
  4. 结果处理:
    • CommonPrefixes: 这是我们主要关注的部分。当Delimiter被使用时,S3会将所有匹配Prefix但被Delimiter分隔的下一级路径作为CommonPrefixes返回。这些就是我们想要的“顶层对象”或“子目录”。注意,CommonPrefixes中的Prefix值通常会以分隔符(/)结尾,你可以使用rtrim()函数去除它,以获得纯粹的目录名。
    • Contents: 这部分会包含直接位于Prefix路径下的文件,即在Prefix之后直到第一个Delimiter之间没有任何Delimiter的对象。如果你的目标是只获取模拟的子目录,可以忽略这部分。

针对原始问题的输出

根据问题中提供的键:

public/uploads/test_company/test1
public/uploads/test_company/test2
public/uploads/test_company/test1/test.txt

如果targetPrefix设置为public/uploads/test_company/,Delimiter设置为/,那么上述代码的$result['CommonPrefixes']部分将包含:

  • Prefix: public/uploads/test_company/test1/
  • Prefix: public/uploads/test_company/test2/

而$result['Contents']部分将为空,因为test1和test2被视为共同前缀的一部分,而不是直接的文件。如果有一个对象键是public/uploads/test_company/direct_file.txt,那么它会出现在Contents中。

注意事项与最佳实践

  • 分页处理: 对于包含大量对象(超过1000个)的桶,listObjects默认只会返回前1000个结果。你需要使用MaxKeys和Marker(或ContinuationToken对于listObjectsV2)参数来实现分页,循环获取所有结果。
  • 性能考虑: 频繁地调用listObjects可能会产生额外的费用和延迟。尽可能优化你的存储结构和访问模式。
  • 权限: 确保你的AWS凭证拥有对S3桶执行s3:ListBucket操作的权限。
  • listObjectsV2: AWS推荐使用listObjectsV2而非listObjects,因为它提供了更好的分页机制(StartAfter和ContinuationToken)。其参数和行为与listObjects在Prefix和Delimiter方面是相同的。

总结

通过巧妙地结合Prefix和Delimiter参数,AWS S3的listObjects(或listObjectsV2)API为我们提供了一种强大而灵活的方式,以模拟文件系统层级结构来浏览和管理S3对象。理解这两个参数的工作原理,特别是Delimiter如何生成CommonPrefixes,是高效利用S3进行对象列表操作的关键。这使得在PHP应用中获取S3桶中特定路径下的顶层“目录”变得简单而直接。

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

650

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1204

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

131

2025.08.07

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

3

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.4万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号