如何在React项目中使用AWS SDK列出S3存储桶中的文件夹
React实现S3存储桶文件夹列表及子对象查看功能
要实现S3存储桶的虚拟文件夹列表和点击查看子内容的功能,关键是利用S3 API的Delimiter和Prefix参数区分虚拟文件夹,以下是具体实现方案:
核心逻辑说明
S3本身没有真实的文件夹概念,所有“文件夹”都是通过对象Key中的/分隔符模拟的。调用listObjectsV2时:
- 设置
Delimiter='/':API会自动把相同前缀的对象归为“文件夹”,返回在CommonPrefixes字段中 - 设置
Prefix:指定要查询的路径前缀,比如根路径为空字符串,子文件夹为folder-name/
代码修改与实现
1. 修正基础配置与状态管理
修复原代码中的参数错误,新增必要状态跟踪当前路径、文件夹列表和文件列表:
import React, { useState, useEffect } from 'react' import AWS from 'aws-sdk'; const Home = () => { // 修正AWS配置:s3Url应改为endpoint AWS.config.update({ accessKeyId: 'your-access-key-id', secretAccessKey: 'your-secret-access-key', endpoint: 'your-s3-endpoint-url', // 比如AWS中国区或自定义存储的端点 s3ForcePathStyle: true, // 自定义存储通常需要开启 }); const s3 = new AWS.S3(); const bucketName = 'your-bucket-name'; // 状态:当前路径前缀、文件夹列表、文件列表 const [currentPrefix, setCurrentPrefix] = useState(''); const [folders, setFolders] = useState([]); const [files, setFiles] = useState([]); // 加载指定路径下的内容 const loadS3Content = () => { const params = { Bucket: bucketName, Delimiter: '/', Prefix: currentPrefix, }; s3.listObjectsV2(params, (err, data) => { if (err) { console.error('加载S3内容失败:', err); return; } // CommonPrefixes是当前路径下的虚拟文件夹 setFolders(data.CommonPrefixes || []); // Contents是当前路径下的文件(排除文件夹本身的空对象) setFiles((data.Contents || []).filter(item => item.Key !== currentPrefix)); }); }; // 初始加载根目录内容,路径变化时重新加载 useEffect(() => { loadS3Content(); }, [currentPrefix]); // 点击文件夹,切换到子路径 const handleFolderClick = (folderPrefix) => { setCurrentPrefix(folderPrefix); }; // 返回上一级目录 const handleGoBack = () => { if (!currentPrefix) return; // 截取上一级路径前缀 const parentPrefix = currentPrefix.split('/').slice(0, -2).join('/') + '/'; setCurrentPrefix(parentPrefix === '/' ? '' : parentPrefix); }; return ( <div> {/* 路径导航 */} <div style={{ marginBottom: 16 }}> <button onClick={handleGoBack} disabled={!currentPrefix}>返回上一级</button> <span style={{ marginLeft: 8 }}>当前路径: {currentPrefix || '根目录'}</span> </div> {/* 文件夹列表 */} <ul style={{ listStyleType: 'none', padding: 0 }}> {folders.map((folder, index) => ( <li key={index} style={{ cursor: 'pointer', color: '#1a0dab', margin: 4 }} onClick={() => handleFolderClick(folder.Prefix)}> 📁 {folder.Prefix.replace(currentPrefix, '').slice(0, -1)} </li> ))} </ul> {/* 文件列表 */} <ul style={{ listStyleType: 'none', padding: 0, marginTop: 16 }}> {files.map((file, index) => ( <li key={index} style={{ margin: 4 }}> 📄 {file.Key.replace(currentPrefix, '')} </li> ))} </ul> </div> ) } export default Home
关键修改点
- 参数修正:将
Delimiter设为'/',利用S3的虚拟文件夹分组能力 - 状态扩展:新增
currentPrefix跟踪当前路径,folders存文件夹列表,files存当前路径下的文件 - 交互逻辑:实现文件夹点击切换路径、返回上一级功能
- 内容过滤:过滤掉文件夹对应的空对象(Key等于当前Prefix的条目)
注意事项
- 密钥安全:绝对不要在前端代码中硬编码AWS密钥,建议通过后端代理请求S3 API,或使用AWS Cognito等身份认证方案
- 分页处理:如果存储桶内容较多,
listObjectsV2会返回NextContinuationToken,需要实现分页加载逻辑 - 端点配置:如果使用非AWS官方S3服务(如MinIO),需正确配置
endpoint和s3ForcePathStyle参数
内容的提问来源于stack exchange,提问作者Sakshi Halge
相关产品推荐
相关产品推荐

