如何通过日期时间从Laravel的Amazon S3存储桶筛选获取文件
Laravel S3按日期筛选文件解决进程终止问题
你的问题核心是$disk->files()会一次性把所有文件路径加载到内存,文件量过大时直接导致内存溢出进程终止。下面是几种可行的解决方案:
1. 利用S3原生API分页筛选(推荐)
Laravel Storage底层基于Flysystem,可直接调用S3客户端的分页接口,每次仅加载一页文件(默认1000条),再在本地筛选符合日期条件的文件,避免内存爆仓:
use Illuminate\Support\Facades\Storage; $disk = Storage::disk('<disk>'); $s3Client = $disk->getDriver()->getAdapter()->getClient(); // 定义筛选的起始时间(示例:2024年5月1日之后创建的文件) $startTimestamp = (new DateTime('2024-05-01 00:00:00'))->getTimestamp(); $folder = rtrim('<folder>', '/') . '/'; $matchedFiles = []; $nextToken = null; do { $response = $s3Client->listObjectsV2([ 'Bucket' => $disk->getConfig()['bucket'], 'Prefix' => $folder, 'ContinuationToken' => $nextToken, ]); // 遍历当前页文件,筛选符合日期条件的 foreach ($response['Contents'] ?? [] as $object) { if ($object['LastModified']->getTimestamp() >= $startTimestamp) { $matchedFiles[] = $object['Key']; } } $nextToken = $response['NextContinuationToken'] ?? null; } while ($nextToken);
2. 使用Flysystem迭代器遍历筛选
Flysystem的listContents方法返回迭代器,不会一次性加载所有文件到内存,适合低内存环境:
use Illuminate\Support\Facades\Storage; $disk = Storage::disk('<disk>'); $startTimestamp = (new DateTime('2024-05-01 00:00:00'))->getTimestamp(); $folder = '<folder>'; $matchedFiles = []; // 第二个参数true表示递归遍历子文件夹,false则只遍历当前文件夹 $iterator = $disk->getDriver()->listContents($folder, true); foreach ($iterator as $item) { // 只处理文件,排除文件夹 if ($item['type'] === 'file' && $item['lastModified'] >= $startTimestamp) { $matchedFiles[] = $item['path']; } }
3. 提前按日期组织文件结构(最优预防方案)
如果可以控制文件存储路径,建议按年/月/日的层级存储文件(比如2024/05/01/xxx.pdf),这样无需筛选,直接读取对应日期的文件夹即可,效率最高:
// 读取2024年5月1日的所有文件 $targetFolder = '2024/05/01'; $files = $disk->files($targetFolder);
内容的提问来源于stack exchange,提问作者CodeZoe
相关产品推荐
相关产品推荐

